ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

dma.c
Go to the documentation of this file.
00001 /*
00002  *
00003  * COPYRIGHT:       See COPYING in the top level directory
00004  * PROJECT:         ReactOS kernel
00005  * FILE:            ntoskrnl/hal/x86/dma.c
00006  * PURPOSE:         DMA functions
00007  * PROGRAMMERS:     David Welch (welch@mcmail.com)
00008  *                  Filip Navara (navaraf@reactos.com)
00009  * UPDATE HISTORY:
00010  *                  Created 22/05/98
00011  */
00012 
00072 /* INCLUDES *****************************************************************/
00073 
00074 #include <hal.h>
00075 #define NDEBUG
00076 #include <debug.h>
00077 
00078 #define MAX_SG_ELEMENTS 0x10
00079 
00080 #ifndef _MINIHAL_
00081 static KEVENT HalpDmaLock;
00082 static LIST_ENTRY HalpDmaAdapterList;
00083 static PADAPTER_OBJECT HalpEisaAdapter[8];
00084 #endif
00085 static BOOLEAN HalpEisaDma;
00086 #ifndef _MINIHAL_
00087 static PADAPTER_OBJECT HalpMasterAdapter;
00088 #endif
00089 
00090 static const ULONG_PTR HalpEisaPortPage[8] = {
00091    FIELD_OFFSET(DMA_PAGE, Channel0),
00092    FIELD_OFFSET(DMA_PAGE, Channel1),
00093    FIELD_OFFSET(DMA_PAGE, Channel2),
00094    FIELD_OFFSET(DMA_PAGE, Channel3),
00095    0,
00096    FIELD_OFFSET(DMA_PAGE, Channel5),
00097    FIELD_OFFSET(DMA_PAGE, Channel6),
00098    FIELD_OFFSET(DMA_PAGE, Channel7)
00099 };
00100 
00101 #ifndef _MINIHAL_
00102 static DMA_OPERATIONS HalpDmaOperations = {
00103    sizeof(DMA_OPERATIONS),
00104    (PPUT_DMA_ADAPTER)HalPutDmaAdapter,
00105    (PALLOCATE_COMMON_BUFFER)HalAllocateCommonBuffer,
00106    (PFREE_COMMON_BUFFER)HalFreeCommonBuffer,
00107    NULL, /* Initialized in HalpInitDma() */
00108    NULL, /* Initialized in HalpInitDma() */
00109    NULL, /* Initialized in HalpInitDma() */
00110    NULL, /* Initialized in HalpInitDma() */
00111    NULL, /* Initialized in HalpInitDma() */
00112    (PGET_DMA_ALIGNMENT)HalpDmaGetDmaAlignment,
00113    (PREAD_DMA_COUNTER)HalReadDmaCounter,
00114    /* FIXME: Implement the S/G funtions. */
00115    (PGET_SCATTER_GATHER_LIST)HalGetScatterGatherList,
00116    (PPUT_SCATTER_GATHER_LIST)HalPutScatterGatherList,
00117    NULL /*(PCALCULATE_SCATTER_GATHER_LIST_SIZE)HalCalculateScatterGatherListSize*/,
00118    NULL /*(PBUILD_SCATTER_GATHER_LIST)HalBuildScatterGatherList*/,
00119    NULL /*(PBUILD_MDL_FROM_SCATTER_GATHER_LIST)HalBuildMdlFromScatterGatherList*/
00120 };
00121 #endif
00122 
00123 #define MAX_MAP_REGISTERS 64
00124 
00125 #define TAG_DMA ' AMD'
00126 
00127 /* FUNCTIONS *****************************************************************/
00128 
00129 #ifndef _MINIHAL_
00130 VOID
00131 INIT_FUNCTION
00132 HalpInitDma(VOID)
00133 {
00134     /*
00135      * Initialize the DMA Operation table
00136      */
00137     HalpDmaOperations.AllocateAdapterChannel = (PALLOCATE_ADAPTER_CHANNEL)IoAllocateAdapterChannel;
00138     HalpDmaOperations.FlushAdapterBuffers = (PFLUSH_ADAPTER_BUFFERS)IoFlushAdapterBuffers;
00139     HalpDmaOperations.FreeAdapterChannel = (PFREE_ADAPTER_CHANNEL)IoFreeAdapterChannel;
00140     HalpDmaOperations.FreeMapRegisters = (PFREE_MAP_REGISTERS)IoFreeMapRegisters;
00141     HalpDmaOperations.MapTransfer = (PMAP_TRANSFER)IoMapTransfer;
00142 
00143     /*
00144      * Check if Extended DMA is available. We're just going to do a random
00145      * read and write.
00146      */
00147     WRITE_PORT_UCHAR((PUCHAR)FIELD_OFFSET(EISA_CONTROL, DmaController2Pages.Channel2), 0x2A);
00148     if (READ_PORT_UCHAR((PUCHAR)FIELD_OFFSET(EISA_CONTROL, DmaController2Pages.Channel2)) == 0x2A)
00149     {
00150         HalpEisaDma = TRUE;
00151     }
00152 
00153     /*
00154      * Intialize all the global variables and allocate master adapter with
00155      * first map buffers.
00156      */
00157     InitializeListHead(&HalpDmaAdapterList);
00158     KeInitializeEvent(&HalpDmaLock, NotificationEvent, TRUE);
00159     HalpMasterAdapter = HalpDmaAllocateMasterAdapter();
00160 
00161     /*
00162      * Setup the HalDispatchTable callback for creating PnP DMA adapters. It's
00163      * used by IoGetDmaAdapter in the kernel.
00164      */
00165     HalGetDmaAdapter = HalpGetDmaAdapter;
00166 }
00167 #endif
00168 
00175 PHYSICAL_ADDRESS
00176 NTAPI
00177 HalpGetAdapterMaximumPhysicalAddress(IN PADAPTER_OBJECT AdapterObject)
00178 {
00179     PHYSICAL_ADDRESS HighestAddress;
00180 
00181     if (AdapterObject->MasterDevice)
00182     {
00183         if (AdapterObject->Dma64BitAddresses)
00184         {
00185             HighestAddress.QuadPart = 0xFFFFFFFFFFFFFFFFULL;
00186             return HighestAddress;
00187         }
00188         else if (AdapterObject->Dma32BitAddresses)
00189         {
00190             HighestAddress.QuadPart = 0xFFFFFFFF;
00191             return HighestAddress;
00192         }
00193     }
00194 
00195     HighestAddress.QuadPart = 0xFFFFFF;
00196     return HighestAddress;
00197 }
00198 
00199 #ifndef _MINIHAL_
00200 
00211 BOOLEAN
00212 NTAPI
00213 HalpGrowMapBuffers(IN PADAPTER_OBJECT AdapterObject,
00214                   IN ULONG SizeOfMapBuffers)
00215 {
00216     PVOID VirtualAddress;
00217     PHYSICAL_ADDRESS PhysicalAddress;
00218     PHYSICAL_ADDRESS HighestAcceptableAddress;
00219     PHYSICAL_ADDRESS LowestAcceptableAddress;
00220     PHYSICAL_ADDRESS BoundryAddressMultiple;
00221     KIRQL OldIrql;
00222     ULONG MapRegisterCount;
00223 
00224     /* Check if enough map register slots are available. */
00225     MapRegisterCount = BYTES_TO_PAGES(SizeOfMapBuffers);
00226     if (MapRegisterCount + AdapterObject->NumberOfMapRegisters > MAX_MAP_REGISTERS)
00227     {
00228         DPRINT("No more map register slots available! (Current: %d | Requested: %d | Limit: %d)\n",
00229                AdapterObject->NumberOfMapRegisters,
00230                MapRegisterCount,
00231                MAX_MAP_REGISTERS);
00232         return FALSE;
00233     }
00234 
00235     /*
00236      * Allocate memory for the new map registers. For 32-bit adapters we use
00237      * two passes in order not to waste scare resource (low memory).
00238      */
00239     HighestAcceptableAddress = HalpGetAdapterMaximumPhysicalAddress(AdapterObject);
00240     LowestAcceptableAddress.HighPart = 0;
00241     LowestAcceptableAddress.LowPart = HighestAcceptableAddress.LowPart == 0xFFFFFFFF ? 0x1000000 : 0;
00242     BoundryAddressMultiple.QuadPart = 0;
00243 
00244     VirtualAddress = MmAllocateContiguousMemorySpecifyCache(MapRegisterCount << PAGE_SHIFT,
00245                                                             LowestAcceptableAddress,
00246                                                             HighestAcceptableAddress,
00247                                                             BoundryAddressMultiple,
00248                                                             MmNonCached);
00249     if (!(VirtualAddress) && (LowestAcceptableAddress.LowPart))
00250     {
00251         LowestAcceptableAddress.LowPart = 0;
00252         VirtualAddress = MmAllocateContiguousMemorySpecifyCache(MapRegisterCount << PAGE_SHIFT,
00253                                                                 LowestAcceptableAddress,
00254                                                                 HighestAcceptableAddress,
00255                                                                 BoundryAddressMultiple,
00256                                                                 MmNonCached);
00257     }
00258 
00259     if (!VirtualAddress) return FALSE;
00260 
00261     PhysicalAddress = MmGetPhysicalAddress(VirtualAddress);
00262 
00263     /*
00264      * All the following must be done with the master adapter lock held
00265      * to prevent corruption.
00266      */
00267     KeAcquireSpinLock(&AdapterObject->SpinLock, &OldIrql);
00268 
00269     /*
00270      * Setup map register entries for the buffer allocated. Each entry has
00271      * a virtual and physical address and corresponds to PAGE_SIZE large
00272      * buffer.
00273      */
00274     if (MapRegisterCount > 0)
00275     {
00276         PROS_MAP_REGISTER_ENTRY CurrentEntry, PreviousEntry;
00277 
00278         CurrentEntry = AdapterObject->MapRegisterBase + AdapterObject->NumberOfMapRegisters;
00279         do
00280         {
00281             /*
00282              * Leave one entry free for every non-contiguous memory region
00283              * in the map register bitmap. This ensures that we can search
00284              * using RtlFindClearBits for contiguous map register regions.
00285              *
00286              * Also for non-EISA DMA leave one free entry for every 64Kb
00287              * break, because the DMA controller can handle only coniguous
00288              * 64Kb regions.
00289              */
00290             if (CurrentEntry != AdapterObject->MapRegisterBase)
00291             {
00292                 PreviousEntry = CurrentEntry - 1;
00293                 if ((PreviousEntry->PhysicalAddress.LowPart + PAGE_SIZE) == PhysicalAddress.LowPart)
00294                 {
00295                     if (!HalpEisaDma)
00296                     {
00297                         if ((PreviousEntry->PhysicalAddress.LowPart ^ PhysicalAddress.LowPart) & 0xFFFF0000)
00298                         {
00299                             CurrentEntry++;
00300                             AdapterObject->NumberOfMapRegisters++;
00301                         }
00302                     }
00303                 }
00304                 else
00305                 {
00306                     CurrentEntry++;
00307                     AdapterObject->NumberOfMapRegisters++;
00308                 }
00309             }
00310 
00311             RtlClearBit(AdapterObject->MapRegisters,
00312                         (ULONG)(CurrentEntry - AdapterObject->MapRegisterBase));
00313             CurrentEntry->VirtualAddress = VirtualAddress;
00314             CurrentEntry->PhysicalAddress = PhysicalAddress;
00315 
00316             PhysicalAddress.LowPart += PAGE_SIZE;
00317             VirtualAddress = (PVOID)((ULONG_PTR)VirtualAddress + PAGE_SIZE);
00318 
00319             CurrentEntry++;
00320             AdapterObject->NumberOfMapRegisters++;
00321             MapRegisterCount--;
00322         } while (MapRegisterCount);
00323     }
00324 
00325     KeReleaseSpinLock(&AdapterObject->SpinLock, OldIrql);
00326 
00327     return TRUE;
00328 }
00329 
00338 PADAPTER_OBJECT
00339 NTAPI
00340 HalpDmaAllocateMasterAdapter(VOID)
00341 {
00342     PADAPTER_OBJECT MasterAdapter;
00343     ULONG Size, SizeOfBitmap;
00344 
00345     SizeOfBitmap = MAX_MAP_REGISTERS;
00346     Size = sizeof(ADAPTER_OBJECT);
00347     Size += sizeof(RTL_BITMAP);
00348     Size += (SizeOfBitmap + 7) >> 3;
00349 
00350     MasterAdapter = ExAllocatePoolWithTag(NonPagedPool, Size, TAG_DMA);
00351     if (!MasterAdapter) return NULL;
00352 
00353     RtlZeroMemory(MasterAdapter, Size);
00354 
00355     KeInitializeSpinLock(&MasterAdapter->SpinLock);
00356     InitializeListHead(&MasterAdapter->AdapterQueue);
00357 
00358     MasterAdapter->MapRegisters = (PVOID)(MasterAdapter + 1);
00359     RtlInitializeBitMap(MasterAdapter->MapRegisters,
00360                         (PULONG)(MasterAdapter->MapRegisters + 1),
00361                         SizeOfBitmap);
00362     RtlSetAllBits(MasterAdapter->MapRegisters);
00363     MasterAdapter->NumberOfMapRegisters = 0;
00364     MasterAdapter->CommittedMapRegisters = 0;
00365 
00366     MasterAdapter->MapRegisterBase = ExAllocatePoolWithTag(NonPagedPool,
00367                                                            SizeOfBitmap *
00368                                                            sizeof(ROS_MAP_REGISTER_ENTRY),
00369                                                            TAG_DMA);
00370     if (!MasterAdapter->MapRegisterBase)
00371     {
00372         ExFreePool(MasterAdapter);
00373         return NULL;
00374     }
00375 
00376     RtlZeroMemory(MasterAdapter->MapRegisterBase,
00377                   SizeOfBitmap * sizeof(ROS_MAP_REGISTER_ENTRY));
00378     if (!HalpGrowMapBuffers(MasterAdapter, 0x10000))
00379     {
00380         ExFreePool(MasterAdapter);
00381         return NULL;
00382     }
00383 
00384     return MasterAdapter;
00385 }
00386 
00395 PADAPTER_OBJECT
00396 NTAPI
00397 HalpDmaAllocateChildAdapter(IN ULONG NumberOfMapRegisters,
00398                             IN PDEVICE_DESCRIPTION DeviceDescription)
00399 {
00400     PADAPTER_OBJECT AdapterObject;
00401     OBJECT_ATTRIBUTES ObjectAttributes;
00402     NTSTATUS Status;
00403     HANDLE Handle;
00404 
00405     InitializeObjectAttributes(&ObjectAttributes,
00406                                NULL,
00407                                OBJ_KERNEL_HANDLE | OBJ_PERMANENT,
00408                                NULL,
00409                                NULL);
00410 
00411     Status = ObCreateObject(KernelMode,
00412                             IoAdapterObjectType,
00413                             &ObjectAttributes,
00414                             KernelMode,
00415                             NULL,
00416                             sizeof(ADAPTER_OBJECT),
00417                             0,
00418                             0,
00419                             (PVOID)&AdapterObject);
00420     if (!NT_SUCCESS(Status)) return NULL;
00421 
00422     Status = ObReferenceObjectByPointer(AdapterObject,
00423                                         FILE_READ_DATA | FILE_WRITE_DATA,
00424                                         IoAdapterObjectType,
00425                                         KernelMode);
00426     if (!NT_SUCCESS(Status)) return NULL;
00427 
00428     RtlZeroMemory(AdapterObject, sizeof(ADAPTER_OBJECT));
00429 
00430     Status = ObInsertObject(AdapterObject,
00431                             NULL,
00432                             FILE_READ_DATA | FILE_WRITE_DATA,
00433                             0,
00434                             NULL,
00435                             &Handle);
00436     if (!NT_SUCCESS(Status)) return NULL;
00437 
00438     ZwClose(Handle);
00439 
00440     AdapterObject->DmaHeader.Version = (USHORT)DeviceDescription->Version;
00441     AdapterObject->DmaHeader.Size = sizeof(ADAPTER_OBJECT);
00442     AdapterObject->DmaHeader.DmaOperations = &HalpDmaOperations;
00443     AdapterObject->MapRegistersPerChannel = 1;
00444     AdapterObject->Dma32BitAddresses = DeviceDescription->Dma32BitAddresses;
00445     AdapterObject->ChannelNumber = 0xFF;
00446     AdapterObject->MasterAdapter = HalpMasterAdapter;
00447     KeInitializeDeviceQueue(&AdapterObject->ChannelWaitQueue);
00448 
00449     return AdapterObject;
00450 }
00451 #endif
00452 
00458 BOOLEAN
00459 NTAPI
00460 HalpDmaInitializeEisaAdapter(IN PADAPTER_OBJECT AdapterObject,
00461                              IN PDEVICE_DESCRIPTION DeviceDescription)
00462 {
00463     UCHAR Controller;
00464     DMA_MODE DmaMode = {{0 }};
00465     DMA_EXTENDED_MODE ExtendedMode = {{ 0 }};
00466     PVOID AdapterBaseVa;
00467 
00468     Controller = (DeviceDescription->DmaChannel & 4) ? 2 : 1;
00469 
00470     if (Controller == 1)
00471     {
00472         AdapterBaseVa = (PVOID)FIELD_OFFSET(EISA_CONTROL, DmaController1);
00473     }
00474     else
00475     {
00476         AdapterBaseVa = (PVOID)FIELD_OFFSET(EISA_CONTROL, DmaController2);
00477     }
00478 
00479     AdapterObject->AdapterNumber = Controller;
00480     AdapterObject->ChannelNumber = (UCHAR)(DeviceDescription->DmaChannel & 3);
00481     AdapterObject->PagePort = (PUCHAR)HalpEisaPortPage[DeviceDescription->DmaChannel];
00482     AdapterObject->Width16Bits = FALSE;
00483     AdapterObject->AdapterBaseVa = AdapterBaseVa;
00484 
00485     if (HalpEisaDma)
00486     {
00487         ExtendedMode.ChannelNumber = AdapterObject->ChannelNumber;
00488 
00489         switch (DeviceDescription->DmaSpeed)
00490         {
00491             case Compatible: ExtendedMode.TimingMode = COMPATIBLE_TIMING; break;
00492             case TypeA: ExtendedMode.TimingMode = TYPE_A_TIMING; break;
00493             case TypeB: ExtendedMode.TimingMode = TYPE_B_TIMING; break;
00494             case TypeC: ExtendedMode.TimingMode = BURST_TIMING; break;
00495             default:
00496                 return FALSE;
00497         }
00498 
00499         switch (DeviceDescription->DmaWidth)
00500         {
00501             case Width8Bits: ExtendedMode.TransferSize = B_8BITS; break;
00502             case Width16Bits: ExtendedMode.TransferSize = B_16BITS; break;
00503             case Width32Bits: ExtendedMode.TransferSize = B_32BITS; break;
00504             default:
00505                 return FALSE;
00506         }
00507 
00508         if (Controller == 1)
00509         {
00510             WRITE_PORT_UCHAR((PUCHAR)FIELD_OFFSET(EISA_CONTROL, DmaExtendedMode1),
00511                             ExtendedMode.Byte);
00512         }
00513         else
00514         {
00515             WRITE_PORT_UCHAR((PUCHAR)FIELD_OFFSET(EISA_CONTROL, DmaExtendedMode2),
00516                             ExtendedMode.Byte);
00517         }
00518     }
00519     else
00520     {
00521         /*
00522          * Validate setup for non-busmaster DMA adapter. Secondary controller
00523          * supports only 16-bit transfers and main controller supports only
00524          * 8-bit transfers. Anything else is invalid.
00525          */
00526         if (!DeviceDescription->Master)
00527         {
00528             if ((Controller == 2) && (DeviceDescription->DmaWidth == Width16Bits))
00529             {
00530                 AdapterObject->Width16Bits = TRUE;
00531             }
00532             else if ((Controller != 1) || (DeviceDescription->DmaWidth != Width8Bits))
00533             {
00534                 return FALSE;
00535             }
00536         }
00537     }
00538 
00539     DmaMode.Channel = AdapterObject->ChannelNumber;
00540     DmaMode.AutoInitialize = DeviceDescription->AutoInitialize;
00541 
00542     /*
00543      * Set the DMA request mode.
00544      *
00545      * For (E)ISA bus master devices just unmask (enable) the DMA channel
00546      * and set it to cascade mode. Otherwise just select the right one
00547      * bases on the passed device description.
00548      */
00549     if (DeviceDescription->Master)
00550     {
00551         DmaMode.RequestMode = CASCADE_REQUEST_MODE;
00552         if (Controller == 1)
00553         {
00554             /* Set the Request Data */
00555             WRITE_PORT_UCHAR(&((PDMA1_CONTROL)AdapterBaseVa)->Mode, DmaMode.Byte);
00556 
00557             /* Unmask DMA Channel */
00558             WRITE_PORT_UCHAR(&((PDMA1_CONTROL)AdapterBaseVa)->SingleMask,
00559                              AdapterObject->ChannelNumber | DMA_CLEARMASK);
00560         }
00561         else
00562         {
00563             /* Set the Request Data */
00564             WRITE_PORT_UCHAR(&((PDMA2_CONTROL)AdapterBaseVa)->Mode, DmaMode.Byte);
00565 
00566             /* Unmask DMA Channel */
00567             WRITE_PORT_UCHAR(&((PDMA2_CONTROL)AdapterBaseVa)->SingleMask,
00568                              AdapterObject->ChannelNumber | DMA_CLEARMASK);
00569         }
00570     }
00571     else
00572     {
00573         if (DeviceDescription->DemandMode)
00574         {
00575             DmaMode.RequestMode = DEMAND_REQUEST_MODE;
00576         }
00577         else
00578         {
00579             DmaMode.RequestMode = SINGLE_REQUEST_MODE;
00580         }
00581     }
00582 
00583     AdapterObject->AdapterMode = DmaMode;
00584 
00585     return TRUE;
00586 }
00587 
00588 #ifndef _MINIHAL_
00589 
00604 PADAPTER_OBJECT
00605 NTAPI
00606 HalGetAdapter(IN PDEVICE_DESCRIPTION DeviceDescription,
00607               OUT PULONG NumberOfMapRegisters)
00608 {
00609     PADAPTER_OBJECT AdapterObject = NULL;
00610     BOOLEAN EisaAdapter;
00611     ULONG MapRegisters;
00612     ULONG MaximumLength;
00613 
00614     /* Validate parameters in device description */
00615     if (DeviceDescription->Version > DEVICE_DESCRIPTION_VERSION2) return NULL;
00616 
00617     /*
00618      * See if we're going to use ISA/EISA DMA adapter. These adapters are
00619      * special since they're reused.
00620      *
00621      * Also note that we check for channel number since there are only 8 DMA
00622      * channels on ISA, so any request above this requires new adapter.
00623      */
00624     if (((DeviceDescription->InterfaceType == Eisa) ||
00625          (DeviceDescription->InterfaceType == Isa)) || !(DeviceDescription->Master))
00626     {
00627         if (((DeviceDescription->InterfaceType == Isa) ||
00628              (DeviceDescription->InterfaceType == Eisa)) &&
00629             (DeviceDescription->DmaChannel >= 8))
00630         {
00631             EisaAdapter = FALSE;
00632         }
00633         else
00634         {
00635             EisaAdapter = TRUE;
00636         }
00637     }
00638     else
00639     {
00640         EisaAdapter = FALSE;
00641     }
00642 
00643     /*
00644      * Disallow creating adapter for ISA/EISA DMA channel 4 since it's used
00645      * for cascading the controllers and it's not available for software use.
00646      */
00647     if ((EisaAdapter) && (DeviceDescription->DmaChannel == 4)) return NULL;
00648 
00649     /*
00650      * Calculate the number of map registers.
00651      *
00652      * - For EISA and PCI scatter/gather no map registers are needed.
00653      * - For ISA slave scatter/gather one map register is needed.
00654      * - For all other cases the number of map registers depends on
00655      *   DeviceDescription->MaximumLength.
00656      */
00657     MaximumLength = DeviceDescription->MaximumLength & MAXLONG;
00658     if ((DeviceDescription->ScatterGather) &&
00659         ((DeviceDescription->InterfaceType == Eisa) ||
00660          (DeviceDescription->InterfaceType == PCIBus)))
00661     {
00662         MapRegisters = 0;
00663     }
00664     else if ((DeviceDescription->ScatterGather) && !(DeviceDescription->Master))
00665     {
00666         MapRegisters = 1;
00667     }
00668     else
00669     {
00670         /*
00671          * In the equation below the additional map register added by
00672          * the "+1" accounts for the case when a transfer does not start
00673          * at a page-aligned address.
00674          */
00675         MapRegisters = BYTES_TO_PAGES(MaximumLength) + 1;
00676         if (MapRegisters > 16) MapRegisters = 16;
00677     }
00678 
00679     /*
00680      * Acquire the DMA lock that is used to protect adapter lists and
00681      * EISA adapter array.
00682      */
00683     KeWaitForSingleObject(&HalpDmaLock, Executive, KernelMode, FALSE, NULL);
00684 
00685     /*
00686      * Now we must get ahold of the adapter object. For first eight ISA/EISA
00687      * channels there are static adapter objects that are reused and updated
00688      * on succesive HalGetAdapter calls. In other cases a new adapter object
00689      * is always created and it's to the DMA adapter list (HalpDmaAdapterList).
00690      */
00691     if (EisaAdapter)
00692     {
00693         AdapterObject = HalpEisaAdapter[DeviceDescription->DmaChannel];
00694         if (AdapterObject)
00695         {
00696             if ((AdapterObject->NeedsMapRegisters) &&
00697                 (MapRegisters > AdapterObject->MapRegistersPerChannel))
00698             {
00699                 AdapterObject->MapRegistersPerChannel = MapRegisters;
00700             }
00701         }
00702     }
00703 
00704     if (AdapterObject == NULL)
00705     {
00706         AdapterObject = HalpDmaAllocateChildAdapter(MapRegisters, DeviceDescription);
00707         if (AdapterObject == NULL)
00708         {
00709             KeSetEvent(&HalpDmaLock, 0, 0);
00710             return NULL;
00711         }
00712 
00713         if (EisaAdapter)
00714         {
00715             HalpEisaAdapter[DeviceDescription->DmaChannel] = AdapterObject;
00716         }
00717 
00718         if (MapRegisters > 0)
00719         {
00720             AdapterObject->NeedsMapRegisters = TRUE;
00721             AdapterObject->MapRegistersPerChannel = MapRegisters;
00722         }
00723         else
00724         {
00725             AdapterObject->NeedsMapRegisters = FALSE;
00726             if (DeviceDescription->Master)
00727             {
00728                 AdapterObject->MapRegistersPerChannel = BYTES_TO_PAGES(MaximumLength) + 1;
00729             }
00730             else
00731             {
00732                 AdapterObject->MapRegistersPerChannel = 1;
00733             }
00734         }
00735     }
00736 
00737     if (!EisaAdapter) InsertTailList(&HalpDmaAdapterList, &AdapterObject->AdapterList);
00738 
00739     /*
00740      * Release the DMA lock. HalpDmaAdapterList and HalpEisaAdapter will
00741      * no longer be touched, so we don't need it.
00742      */
00743     KeSetEvent(&HalpDmaLock, 0, 0);
00744 
00745     /*
00746      * Setup the values in the adapter object that are common for all
00747      * types of buses.
00748      */
00749     if (DeviceDescription->Version >= DEVICE_DESCRIPTION_VERSION1)
00750     {
00751         AdapterObject->IgnoreCount = DeviceDescription->IgnoreCount;
00752     }
00753     else
00754     {
00755         AdapterObject->IgnoreCount = 0;
00756     }
00757 
00758     AdapterObject->Dma32BitAddresses = DeviceDescription->Dma32BitAddresses;
00759     AdapterObject->Dma64BitAddresses = DeviceDescription->Dma64BitAddresses;
00760     AdapterObject->ScatterGather = DeviceDescription->ScatterGather;
00761     AdapterObject->MasterDevice = DeviceDescription->Master;
00762     *NumberOfMapRegisters = AdapterObject->MapRegistersPerChannel;
00763 
00764     /*
00765      * For non-(E)ISA adapters we have already done all the work. On the
00766      * other hand for (E)ISA adapters we must still setup the DMA modes
00767      * and prepare the controller.
00768      */
00769     if (EisaAdapter)
00770     {
00771         if (!HalpDmaInitializeEisaAdapter(AdapterObject, DeviceDescription))
00772         {
00773             ObDereferenceObject(AdapterObject);
00774             return NULL;
00775         }
00776     }
00777 
00778     return AdapterObject;
00779 }
00780 
00789 PDMA_ADAPTER
00790 NTAPI
00791 HalpGetDmaAdapter(IN PVOID Context,
00792                   IN PDEVICE_DESCRIPTION DeviceDescription,
00793                   OUT PULONG NumberOfMapRegisters)
00794 {
00795     return &HalGetAdapter(DeviceDescription, NumberOfMapRegisters)->DmaHeader;
00796 }
00797 
00806 VOID
00807 NTAPI
00808 HalPutDmaAdapter(IN PADAPTER_OBJECT AdapterObject)
00809 {
00810     if (AdapterObject->ChannelNumber == 0xFF)
00811     {
00812         KeWaitForSingleObject(&HalpDmaLock, Executive, KernelMode, FALSE, NULL);
00813         RemoveEntryList(&AdapterObject->AdapterList);
00814         KeSetEvent(&HalpDmaLock, 0, 0);
00815     }
00816 
00817     ObDereferenceObject(AdapterObject);
00818 }
00819 
00845 PVOID
00846 NTAPI
00847 HalAllocateCommonBuffer(IN PADAPTER_OBJECT AdapterObject,
00848                         IN ULONG Length,
00849                         IN PPHYSICAL_ADDRESS LogicalAddress,
00850                         IN BOOLEAN CacheEnabled)
00851 {
00852     PHYSICAL_ADDRESS LowestAcceptableAddress;
00853     PHYSICAL_ADDRESS HighestAcceptableAddress;
00854     PHYSICAL_ADDRESS BoundryAddressMultiple;
00855     PVOID VirtualAddress;
00856 
00857     LowestAcceptableAddress.QuadPart = 0;
00858     HighestAcceptableAddress = HalpGetAdapterMaximumPhysicalAddress(AdapterObject);
00859     BoundryAddressMultiple.QuadPart = 0;
00860 
00861     /*
00862      * For bus-master DMA devices the buffer mustn't cross 4Gb boundary. For
00863      * slave DMA devices the 64Kb boundary mustn't be crossed since the
00864      * controller wouldn't be able to handle it.
00865      */
00866     if (AdapterObject->MasterDevice)
00867     {
00868         BoundryAddressMultiple.HighPart = 1;
00869     }
00870     else
00871     {
00872         BoundryAddressMultiple.LowPart = 0x10000;
00873     }
00874 
00875     VirtualAddress = MmAllocateContiguousMemorySpecifyCache(Length,
00876                                                             LowestAcceptableAddress,
00877                                                             HighestAcceptableAddress,
00878                                                             BoundryAddressMultiple,
00879                                                             CacheEnabled ? MmCached :
00880                                                             MmNonCached);
00881     if (VirtualAddress == NULL) return NULL;
00882 
00883     *LogicalAddress = MmGetPhysicalAddress(VirtualAddress);
00884 
00885     return VirtualAddress;
00886 }
00887 
00897 VOID
00898 NTAPI
00899 HalFreeCommonBuffer(IN PADAPTER_OBJECT AdapterObject,
00900                     IN ULONG Length,
00901                     IN PHYSICAL_ADDRESS LogicalAddress,
00902                     IN PVOID VirtualAddress,
00903                     IN BOOLEAN CacheEnabled)
00904 {
00905     MmFreeContiguousMemorySpecifyCache(VirtualAddress,
00906                                        Length,
00907                                        CacheEnabled ? MmCached : MmNonCached);
00908 }
00909 
00910 typedef struct _SCATTER_GATHER_CONTEXT {
00911     PADAPTER_OBJECT AdapterObject;
00912     PMDL Mdl;
00913     PUCHAR CurrentVa;
00914     ULONG Length;
00915     PDRIVER_LIST_CONTROL AdapterListControlRoutine;
00916     PVOID AdapterListControlContext, MapRegisterBase;
00917     ULONG MapRegisterCount;
00918     BOOLEAN WriteToDevice;
00919 } SCATTER_GATHER_CONTEXT, *PSCATTER_GATHER_CONTEXT;
00920 
00921 
00922 IO_ALLOCATION_ACTION
00923 NTAPI
00924 HalpScatterGatherAdapterControl(IN PDEVICE_OBJECT DeviceObject,
00925                                 IN PIRP Irp,
00926                                 IN PVOID MapRegisterBase,
00927                                 IN PVOID Context)
00928 {
00929     PSCATTER_GATHER_CONTEXT AdapterControlContext = Context;
00930     PADAPTER_OBJECT AdapterObject = AdapterControlContext->AdapterObject;
00931     PSCATTER_GATHER_LIST ScatterGatherList;
00932     SCATTER_GATHER_ELEMENT TempElements[MAX_SG_ELEMENTS];
00933     ULONG ElementCount = 0, RemainingLength = AdapterControlContext->Length;
00934     PUCHAR CurrentVa = AdapterControlContext->CurrentVa;
00935 
00936     /* Store the map register base for later in HalPutScatterGatherList */
00937     AdapterControlContext->MapRegisterBase = MapRegisterBase;
00938 
00939     while (RemainingLength > 0 && ElementCount < MAX_SG_ELEMENTS)
00940     {
00941         TempElements[ElementCount].Length = RemainingLength;
00942         TempElements[ElementCount].Reserved = 0;
00943         TempElements[ElementCount].Address = IoMapTransfer(AdapterObject,
00944                                                            AdapterControlContext->Mdl,
00945                                                            MapRegisterBase,
00946                                                            CurrentVa + (AdapterControlContext->Length - RemainingLength),
00947                                                            &TempElements[ElementCount].Length,
00948                                                            AdapterControlContext->WriteToDevice);
00949         if (TempElements[ElementCount].Length == 0)
00950             break;
00951 
00952         DPRINT("Allocated one S/G element: 0x%I64u with length: 0x%x\n",
00953                 TempElements[ElementCount].Address.QuadPart,
00954                 TempElements[ElementCount].Length);
00955 
00956         ASSERT(TempElements[ElementCount].Length <= RemainingLength);
00957         RemainingLength -= TempElements[ElementCount].Length;
00958         ElementCount++;
00959     }
00960 
00961     if (RemainingLength > 0)
00962     {
00963         DPRINT1("Scatter/gather list construction failed!\n");
00964         return DeallocateObject;
00965     }
00966 
00967     ScatterGatherList = ExAllocatePoolWithTag(NonPagedPool,
00968                                               sizeof(SCATTER_GATHER_LIST) + sizeof(SCATTER_GATHER_ELEMENT) * ElementCount,
00969                                               TAG_DMA);
00970     ASSERT(ScatterGatherList);
00971 
00972     ScatterGatherList->NumberOfElements = ElementCount;
00973     ScatterGatherList->Reserved = (ULONG_PTR)AdapterControlContext;
00974     RtlCopyMemory(ScatterGatherList->Elements,
00975                   TempElements,
00976                   sizeof(SCATTER_GATHER_ELEMENT) * ElementCount);
00977 
00978     DPRINT("Initiating S/G DMA with %d element(s)\n", ElementCount);
00979 
00980     AdapterControlContext->AdapterListControlRoutine(DeviceObject,
00981                                                      Irp,
00982                                                      ScatterGatherList,
00983                                                      AdapterControlContext->AdapterListControlContext);
00984 
00985     return DeallocateObjectKeepRegisters;
00986 }
00987 
01016  NTSTATUS
01017  NTAPI
01018  HalGetScatterGatherList(IN PADAPTER_OBJECT AdapterObject,
01019                          IN PDEVICE_OBJECT DeviceObject,
01020                          IN PMDL Mdl,
01021                          IN PVOID CurrentVa,
01022                          IN ULONG Length,
01023                          IN PDRIVER_LIST_CONTROL ExecutionRoutine,
01024                          IN PVOID Context,
01025                          IN BOOLEAN WriteToDevice)
01026 {
01027     PSCATTER_GATHER_CONTEXT AdapterControlContext;
01028 
01029     AdapterControlContext = ExAllocatePoolWithTag(NonPagedPool, sizeof(SCATTER_GATHER_CONTEXT), TAG_DMA);
01030     if (!AdapterControlContext) return STATUS_INSUFFICIENT_RESOURCES;
01031 
01032     AdapterControlContext->AdapterObject = AdapterObject;
01033     AdapterControlContext->Mdl = Mdl;
01034     AdapterControlContext->CurrentVa = CurrentVa;
01035     AdapterControlContext->Length = Length;
01036     AdapterControlContext->MapRegisterCount = PAGE_ROUND_UP(Length) >> PAGE_SHIFT;
01037     AdapterControlContext->AdapterListControlRoutine = ExecutionRoutine;
01038     AdapterControlContext->AdapterListControlContext = Context;
01039     AdapterControlContext->WriteToDevice = WriteToDevice;
01040 
01041     return IoAllocateAdapterChannel(AdapterObject,
01042                                     DeviceObject,
01043                                     AdapterControlContext->MapRegisterCount,
01044                                     HalpScatterGatherAdapterControl,
01045                                     AdapterControlContext);
01046 }
01047 
01066  VOID
01067  NTAPI
01068  HalPutScatterGatherList(IN PADAPTER_OBJECT AdapterObject,
01069                          IN PSCATTER_GATHER_LIST ScatterGather,
01070                          IN BOOLEAN WriteToDevice)
01071 {
01072     PSCATTER_GATHER_CONTEXT AdapterControlContext = (PSCATTER_GATHER_CONTEXT)ScatterGather->Reserved;
01073     ULONG i;
01074 
01075     for (i = 0; i < ScatterGather->NumberOfElements; i++)
01076     {
01077          IoFlushAdapterBuffers(AdapterObject,
01078                                AdapterControlContext->Mdl,
01079                                AdapterControlContext->MapRegisterBase,
01080                                AdapterControlContext->CurrentVa,
01081                                ScatterGather->Elements[i].Length,
01082                                AdapterControlContext->WriteToDevice);
01083          AdapterControlContext->CurrentVa += ScatterGather->Elements[i].Length;
01084     }
01085 
01086     IoFreeMapRegisters(AdapterObject,
01087                        AdapterControlContext->MapRegisterBase,
01088                        AdapterControlContext->MapRegisterCount);
01089 
01090     DPRINT("S/G DMA has finished!\n");
01091 
01092     ExFreePoolWithTag(AdapterControlContext, TAG_DMA);
01093     ExFreePoolWithTag(ScatterGather, TAG_DMA);
01094 }
01095 #endif
01096 
01105 ULONG
01106 NTAPI
01107 HalpDmaGetDmaAlignment(IN PADAPTER_OBJECT AdapterObject)
01108 {
01109     return 1;
01110 }
01111 
01112 /*
01113  * @name HalReadDmaCounter
01114  *
01115  * Read DMA operation progress counter.
01116  *
01117  * @implemented
01118  */
01119 ULONG
01120 NTAPI
01121 HalReadDmaCounter(IN PADAPTER_OBJECT AdapterObject)
01122 {
01123     KIRQL OldIrql;
01124     ULONG Count, OldCount;
01125 
01126     ASSERT(!AdapterObject->MasterDevice);
01127 
01128     /*
01129      * Acquire the master adapter lock since we're going to mess with the
01130      * system DMA controller registers and we really don't want anyone
01131      * to do the same at the same time.
01132      */
01133     KeAcquireSpinLock(&AdapterObject->MasterAdapter->SpinLock, &OldIrql);
01134 
01135     /* Send the request to the specific controller. */
01136     if (AdapterObject->AdapterNumber == 1)
01137     {
01138         PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa;
01139 
01140         Count = 0xffff00;
01141         do
01142         {
01143             OldCount = Count;
01144 
01145             /* Send Reset */
01146             WRITE_PORT_UCHAR(&DmaControl1->ClearBytePointer, 0);
01147 
01148             /* Read Count */
01149             Count = READ_PORT_UCHAR(&DmaControl1->DmaAddressCount
01150                                     [AdapterObject->ChannelNumber].DmaBaseCount);
01151             Count |= READ_PORT_UCHAR(&DmaControl1->DmaAddressCount
01152                                      [AdapterObject->ChannelNumber].DmaBaseCount) << 8;
01153         } while (0xffff00 & (OldCount ^ Count));
01154     }
01155     else
01156     {
01157         PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa;
01158 
01159         Count = 0xffff00;
01160         do
01161         {
01162             OldCount = Count;
01163 
01164             /* Send Reset */
01165             WRITE_PORT_UCHAR(&DmaControl2->ClearBytePointer, 0);
01166 
01167             /* Read Count */
01168             Count = READ_PORT_UCHAR(&DmaControl2->DmaAddressCount
01169                                     [AdapterObject->ChannelNumber].DmaBaseCount);
01170             Count |= READ_PORT_UCHAR(&DmaControl2->DmaAddressCount
01171                                      [AdapterObject->ChannelNumber].DmaBaseCount) << 8;
01172         } while (0xffff00 & (OldCount ^ Count));
01173     }
01174 
01175     KeReleaseSpinLock(&AdapterObject->MasterAdapter->SpinLock, OldIrql);
01176 
01177     Count++;
01178     Count &= 0xffff;
01179     if (AdapterObject->Width16Bits) Count *= 2;
01180 
01181     return Count;
01182 }
01183 
01184 #ifndef _MINIHAL_
01185 
01191 VOID
01192 NTAPI
01193 HalpGrowMapBufferWorker(IN PVOID DeferredContext)
01194 {
01195     PGROW_WORK_ITEM WorkItem = (PGROW_WORK_ITEM)DeferredContext;
01196     KIRQL OldIrql;
01197     BOOLEAN Succeeded;
01198 
01199     /*
01200      * Try to allocate new map registers for the adapter.
01201      *
01202      * NOTE: The NT implementation actually tries to allocate more map
01203      * registers than needed as an optimization.
01204      */
01205     KeWaitForSingleObject(&HalpDmaLock, Executive, KernelMode, FALSE, NULL);
01206     Succeeded = HalpGrowMapBuffers(WorkItem->AdapterObject->MasterAdapter,
01207                                    WorkItem->NumberOfMapRegisters << PAGE_SHIFT);
01208     KeSetEvent(&HalpDmaLock, 0, 0);
01209 
01210     if (Succeeded)
01211     {
01212         /*
01213          * Flush the adapter queue now that new map registers are ready. The
01214          * easiest way to do that is to call IoFreeMapRegisters to not free
01215          * any registers. Note that we use the magic (PVOID)2 map register
01216          * base to bypass the parameter checking.
01217          */
01218         OldIrql = KfRaiseIrql(DISPATCH_LEVEL);
01219         IoFreeMapRegisters(WorkItem->AdapterObject, (PVOID)2, 0);
01220         KfLowerIrql(OldIrql);
01221     }
01222 
01223     ExFreePool(WorkItem);
01224 }
01225 
01250 NTSTATUS
01251 NTAPI
01252 HalAllocateAdapterChannel(IN PADAPTER_OBJECT AdapterObject,
01253                           IN PWAIT_CONTEXT_BLOCK WaitContextBlock,
01254                           IN ULONG NumberOfMapRegisters,
01255                           IN PDRIVER_CONTROL ExecutionRoutine)
01256 {
01257     PADAPTER_OBJECT MasterAdapter;
01258     PGROW_WORK_ITEM WorkItem;
01259     ULONG Index = MAXULONG;
01260     ULONG Result;
01261     KIRQL OldIrql;
01262 
01263     ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
01264 
01265     /* Set up the wait context block in case we can't run right away. */
01266     WaitContextBlock->DeviceRoutine = ExecutionRoutine;
01267     WaitContextBlock->NumberOfMapRegisters = NumberOfMapRegisters;
01268 
01269     /* Returns true if queued, else returns false and sets the queue to busy */
01270     if (KeInsertDeviceQueue(&AdapterObject->ChannelWaitQueue,
01271                             &WaitContextBlock->WaitQueueEntry))
01272     {
01273         return STATUS_SUCCESS;
01274     }
01275 
01276     MasterAdapter = AdapterObject->MasterAdapter;
01277 
01278     AdapterObject->NumberOfMapRegisters = NumberOfMapRegisters;
01279     AdapterObject->CurrentWcb = WaitContextBlock;
01280 
01281     if ((NumberOfMapRegisters) && (AdapterObject->NeedsMapRegisters))
01282     {
01283         if (NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel)
01284         {
01285             AdapterObject->NumberOfMapRegisters = 0;
01286             IoFreeAdapterChannel(AdapterObject);
01287             return STATUS_INSUFFICIENT_RESOURCES;
01288         }
01289 
01290         /*
01291          * Get the map registers. This is partly complicated by the fact
01292          * that new map registers can only be allocated at PASSIVE_LEVEL
01293          * and we're currently at DISPATCH_LEVEL. The following code has
01294          * two code paths:
01295          *
01296          * - If there is no adapter queued for map register allocation,
01297          *   try to see if enough contiguous map registers are present.
01298          *   In case they're we can just get them and proceed further.
01299          *
01300          * - If some adapter is already present in the queue we must
01301          *   respect the order of adapters asking for map registers and
01302          *   so the fast case described above can't take place.
01303          *   This case is also entered if not enough coniguous map
01304          *   registers are present.
01305          *
01306          *   A work queue item is allocated and queued, the adapter is
01307          *   also queued into the master adapter queue. The worker
01308          *   routine does the job of allocating the map registers at
01309          *   PASSIVE_LEVEL and calling the ExecutionRoutine.
01310          */
01311 
01312         KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql);
01313 
01314         if (IsListEmpty(&MasterAdapter->AdapterQueue))
01315         {
01316             Index = RtlFindClearBitsAndSet(MasterAdapter->MapRegisters, NumberOfMapRegisters, 0);
01317             if (Index != MAXULONG)
01318             {
01319                 AdapterObject->MapRegisterBase = MasterAdapter->MapRegisterBase + Index;
01320                 if (!AdapterObject->ScatterGather)
01321                 {
01322                     AdapterObject->MapRegisterBase = (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)AdapterObject->MapRegisterBase | MAP_BASE_SW_SG);
01323                 }
01324             }
01325         }
01326 
01327         if (Index == MAXULONG)
01328         {
01329             InsertTailList(&MasterAdapter->AdapterQueue, &AdapterObject->AdapterQueue);
01330 
01331             WorkItem = ExAllocatePoolWithTag(NonPagedPool,
01332                                              sizeof(GROW_WORK_ITEM),
01333                                              TAG_DMA);
01334             if (WorkItem)
01335             {
01336                 ExInitializeWorkItem(&WorkItem->WorkQueueItem, HalpGrowMapBufferWorker, WorkItem);
01337                 WorkItem->AdapterObject = AdapterObject;
01338                 WorkItem->NumberOfMapRegisters = NumberOfMapRegisters;
01339 
01340                 ExQueueWorkItem(&WorkItem->WorkQueueItem, DelayedWorkQueue);
01341             }
01342 
01343             KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
01344 
01345             return STATUS_SUCCESS;
01346         }
01347 
01348         KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
01349     }
01350     else
01351     {
01352         AdapterObject->MapRegisterBase = NULL;
01353         AdapterObject->NumberOfMapRegisters = 0;
01354     }
01355 
01356     AdapterObject->CurrentWcb = WaitContextBlock;
01357 
01358     Result = ExecutionRoutine(WaitContextBlock->DeviceObject,
01359                               WaitContextBlock->CurrentIrp,
01360                               AdapterObject->MapRegisterBase,
01361                               WaitContextBlock->DeviceContext);
01362 
01363     /*
01364      * Possible return values:
01365      *
01366      * - KeepObject
01367      *   Don't free any resources, the ADAPTER_OBJECT is still in use and
01368      *   the caller will call IoFreeAdapterChannel later.
01369      *
01370      * - DeallocateObject
01371      *   Deallocate the map registers and release the ADAPTER_OBJECT, so
01372      *   someone else can use it.
01373      *
01374      * - DeallocateObjectKeepRegisters
01375      *   Release the ADAPTER_OBJECT, but hang on to the map registers. The
01376      *   client will later call IoFreeMapRegisters.
01377      *
01378      * NOTE:
01379      * IoFreeAdapterChannel runs the queue, so it must be called unless
01380      * the adapter object is not to be freed.
01381      */
01382     if (Result == DeallocateObject)
01383     {
01384         IoFreeAdapterChannel(AdapterObject);
01385     }
01386     else if (Result == DeallocateObjectKeepRegisters)
01387     {
01388         AdapterObject->NumberOfMapRegisters = 0;
01389         IoFreeAdapterChannel(AdapterObject);
01390     }
01391 
01392     return STATUS_SUCCESS;
01393 }
01394 
01413 VOID
01414 NTAPI
01415 IoFreeAdapterChannel(IN PADAPTER_OBJECT AdapterObject)
01416 {
01417     PADAPTER_OBJECT MasterAdapter;
01418     PKDEVICE_QUEUE_ENTRY DeviceQueueEntry;
01419     PWAIT_CONTEXT_BLOCK WaitContextBlock;
01420     ULONG Index = MAXULONG;
01421     ULONG Result;
01422     KIRQL OldIrql;
01423 
01424     MasterAdapter = AdapterObject->MasterAdapter;
01425 
01426     for (;;)
01427     {
01428         /*
01429          * To keep map registers, call here with AdapterObject->
01430          * NumberOfMapRegisters set to zero. This trick is used in
01431          * HalAllocateAdapterChannel for example.
01432          */
01433         if (AdapterObject->NumberOfMapRegisters)
01434         {
01435             IoFreeMapRegisters(AdapterObject,
01436                                AdapterObject->MapRegisterBase,
01437                                AdapterObject->NumberOfMapRegisters);
01438         }
01439 
01440         DeviceQueueEntry = KeRemoveDeviceQueue(&AdapterObject->ChannelWaitQueue);
01441         if (!DeviceQueueEntry) break;
01442 
01443         WaitContextBlock = CONTAINING_RECORD(DeviceQueueEntry,
01444                                              WAIT_CONTEXT_BLOCK,
01445                                              WaitQueueEntry);
01446 
01447         AdapterObject->CurrentWcb = WaitContextBlock;
01448         AdapterObject->NumberOfMapRegisters = WaitContextBlock->NumberOfMapRegisters;
01449 
01450         if ((WaitContextBlock->NumberOfMapRegisters) && (AdapterObject->MasterAdapter))
01451         {
01452             KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql);
01453 
01454             if (IsListEmpty(&MasterAdapter->AdapterQueue))
01455             {
01456                 Index = RtlFindClearBitsAndSet(MasterAdapter->MapRegisters,
01457                                                WaitContextBlock->NumberOfMapRegisters,
01458                                                0);
01459                 if (Index != MAXULONG)
01460                 {
01461                     AdapterObject->MapRegisterBase = MasterAdapter->MapRegisterBase + Index;
01462                     if (!AdapterObject->ScatterGather)
01463                     {
01464                         AdapterObject->MapRegisterBase =(PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)AdapterObject->MapRegisterBase | MAP_BASE_SW_SG);
01465                     }
01466                 }
01467             }
01468 
01469             if (Index == MAXULONG)
01470             {
01471                 InsertTailList(&MasterAdapter->AdapterQueue, &AdapterObject->AdapterQueue);
01472                 KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
01473                 break;
01474             }
01475 
01476             KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
01477         }
01478         else
01479         {
01480             AdapterObject->MapRegisterBase = NULL;
01481             AdapterObject->NumberOfMapRegisters = 0;
01482         }
01483 
01484         /* Call the adapter control routine. */
01485         Result = ((PDRIVER_CONTROL)WaitContextBlock->DeviceRoutine)(WaitContextBlock->DeviceObject,
01486                                                                     WaitContextBlock->CurrentIrp,
01487                                                                     AdapterObject->MapRegisterBase,
01488                                                                     WaitContextBlock->DeviceContext);
01489         switch (Result)
01490         {
01491             case KeepObject:
01492                 /*
01493                  * We're done until the caller manually calls IoFreeAdapterChannel
01494                  * or IoFreeMapRegisters.
01495                  */
01496                 return;
01497 
01498             case DeallocateObjectKeepRegisters:
01499                 /*
01500                  * Hide the map registers so they aren't deallocated next time
01501                  * around.
01502                  */
01503                 AdapterObject->NumberOfMapRegisters = 0;
01504                 break;
01505 
01506             default:
01507                 break;
01508         }
01509     }
01510 }
01511 
01526 VOID
01527 NTAPI
01528 IoFreeMapRegisters(IN PADAPTER_OBJECT AdapterObject,
01529                    IN PVOID MapRegisterBase,
01530                    IN ULONG NumberOfMapRegisters)
01531 {
01532     PADAPTER_OBJECT MasterAdapter = AdapterObject->MasterAdapter;
01533     PLIST_ENTRY ListEntry;
01534     KIRQL OldIrql;
01535     ULONG Index;
01536     ULONG Result;
01537 
01538     ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
01539 
01540     if (!(MasterAdapter) || !(MapRegisterBase)) return;
01541 
01542     KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql);
01543 
01544     if (NumberOfMapRegisters != 0)
01545     {
01546         PROS_MAP_REGISTER_ENTRY RealMapRegisterBase;
01547 
01548         RealMapRegisterBase = (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)MapRegisterBase & ~MAP_BASE_SW_SG);
01549         RtlClearBits(MasterAdapter->MapRegisters,
01550                      (ULONG)(RealMapRegisterBase - MasterAdapter->MapRegisterBase),
01551                      NumberOfMapRegisters);
01552     }
01553 
01554     /*
01555      * Now that we freed few map registers it's time to look at the master
01556      * adapter queue and see if there is someone waiting for map registers.
01557      */
01558     while (!IsListEmpty(&MasterAdapter->AdapterQueue))
01559     {
01560         ListEntry = RemoveHeadList(&MasterAdapter->AdapterQueue);
01561         AdapterObject = CONTAINING_RECORD(ListEntry, struct _ADAPTER_OBJECT, AdapterQueue);
01562 
01563         Index = RtlFindClearBitsAndSet(MasterAdapter->MapRegisters,
01564                                        AdapterObject->NumberOfMapRegisters,
01565                                        0);
01566         if (Index == MAXULONG)
01567         {
01568             InsertHeadList(&MasterAdapter->AdapterQueue, ListEntry);
01569             break;
01570         }
01571 
01572         KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
01573 
01574         AdapterObject->MapRegisterBase = MasterAdapter->MapRegisterBase + Index;
01575         if (!AdapterObject->ScatterGather)
01576         {
01577             AdapterObject->MapRegisterBase =
01578                 (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)AdapterObject->MapRegisterBase | MAP_BASE_SW_SG);
01579         }
01580 
01581         Result = ((PDRIVER_CONTROL)AdapterObject->CurrentWcb->DeviceRoutine)(AdapterObject->CurrentWcb->DeviceObject,
01582                                                                              AdapterObject->CurrentWcb->CurrentIrp,
01583                                                                              AdapterObject->MapRegisterBase,
01584                                                                              AdapterObject->CurrentWcb->DeviceContext);
01585         switch (Result)
01586         {
01587             case DeallocateObjectKeepRegisters:
01588                 AdapterObject->NumberOfMapRegisters = 0;
01589                 /* fall through */
01590 
01591             case DeallocateObject:
01592                 if (AdapterObject->NumberOfMapRegisters)
01593                 {
01594                     KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql);
01595                     RtlClearBits(MasterAdapter->MapRegisters,
01596                                  (ULONG)(AdapterObject->MapRegisterBase -
01597                                          MasterAdapter->MapRegisterBase),
01598                                  AdapterObject->NumberOfMapRegisters);
01599                     KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
01600                 }
01601 
01602                 IoFreeAdapterChannel(AdapterObject);
01603                 break;
01604 
01605             default:
01606                 break;
01607         }
01608 
01609         KeAcquireSpinLock(&MasterAdapter->SpinLock, &OldIrql);
01610     }
01611 
01612     KeReleaseSpinLock(&MasterAdapter->SpinLock, OldIrql);
01613 }
01614 
01622 VOID
01623 NTAPI
01624 HalpCopyBufferMap(IN PMDL Mdl,
01625                   IN PROS_MAP_REGISTER_ENTRY MapRegisterBase,
01626                   IN PVOID CurrentVa,
01627                   IN ULONG Length,
01628                   IN BOOLEAN WriteToDevice)
01629 {
01630     ULONG CurrentLength;
01631     ULONG_PTR CurrentAddress;
01632     ULONG ByteOffset;
01633     PVOID VirtualAddress;
01634 
01635     VirtualAddress = MmGetSystemAddressForMdlSafe(Mdl, HighPagePriority);
01636     if (!VirtualAddress)
01637     {
01638         /*
01639          * NOTE: On real NT a mechanism with reserved pages is implemented
01640          * to handle this case in a slow, but graceful non-fatal way.
01641          */
01642          KeBugCheckEx(HAL_MEMORY_ALLOCATION, PAGE_SIZE, 0, (ULONG_PTR)__FILE__, 0);
01643     }
01644 
01645     CurrentAddress = (ULONG_PTR)VirtualAddress +
01646                      (ULONG_PTR)CurrentVa -
01647                      (ULONG_PTR)MmGetMdlVirtualAddress(Mdl);
01648 
01649     while (Length > 0)
01650     {
01651         ByteOffset = BYTE_OFFSET(CurrentAddress);
01652         CurrentLength = PAGE_SIZE - ByteOffset;
01653         if (CurrentLength > Length) CurrentLength = Length;
01654 
01655         if (WriteToDevice)
01656         {
01657             RtlCopyMemory((PVOID)((ULONG_PTR)MapRegisterBase->VirtualAddress + ByteOffset),
01658                           (PVOID)CurrentAddress,
01659                           CurrentLength);
01660         }
01661         else
01662         {
01663             RtlCopyMemory((PVOID)CurrentAddress,
01664                           (PVOID)((ULONG_PTR)MapRegisterBase->VirtualAddress + ByteOffset),
01665                           CurrentLength);
01666         }
01667 
01668         Length -= CurrentLength;
01669         CurrentAddress += CurrentLength;
01670         MapRegisterBase++;
01671     }
01672 }
01673 
01705 BOOLEAN
01706 NTAPI
01707 IoFlushAdapterBuffers(IN PADAPTER_OBJECT AdapterObject,
01708                       IN PMDL Mdl,
01709                       IN PVOID MapRegisterBase,
01710                       IN PVOID CurrentVa,
01711                       IN ULONG Length,
01712                       IN BOOLEAN WriteToDevice)
01713 {
01714     BOOLEAN SlaveDma = FALSE;
01715     PROS_MAP_REGISTER_ENTRY RealMapRegisterBase;
01716     PHYSICAL_ADDRESS HighestAcceptableAddress;
01717     PHYSICAL_ADDRESS PhysicalAddress;
01718     PPFN_NUMBER MdlPagesPtr;
01719 
01720     /* Sanity checks */
01721     ASSERT_IRQL_LESS_OR_EQUAL(DISPATCH_LEVEL);
01722     ASSERT(AdapterObject);
01723 
01724     if (!AdapterObject->MasterDevice)
01725     {
01726         /* Mask out (disable) the DMA channel. */
01727         if (AdapterObject->AdapterNumber == 1)
01728         {
01729             PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa;
01730             WRITE_PORT_UCHAR(&DmaControl1->SingleMask,
01731                              AdapterObject->ChannelNumber | DMA_SETMASK);
01732         }
01733         else
01734         {
01735             PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa;
01736             WRITE_PORT_UCHAR(&DmaControl2->SingleMask,
01737                              AdapterObject->ChannelNumber | DMA_SETMASK);
01738         }
01739         SlaveDma = TRUE;
01740     }
01741 
01742     /* This can happen if the device supports hardware scatter/gather. */
01743     if (MapRegisterBase == NULL) return TRUE;
01744 
01745     RealMapRegisterBase = (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)MapRegisterBase & ~MAP_BASE_SW_SG);
01746 
01747     if (!WriteToDevice)
01748     {
01749         if ((ULONG_PTR)MapRegisterBase & MAP_BASE_SW_SG)
01750         {
01751             if (RealMapRegisterBase->Counter != MAXULONG)
01752             {
01753                 if ((SlaveDma) && !(AdapterObject->IgnoreCount))
01754                 {
01755                     Length -= HalReadDmaCounter(AdapterObject);
01756                 }
01757             }
01758             HalpCopyBufferMap(Mdl,
01759                               RealMapRegisterBase,
01760                               CurrentVa,
01761                               Length,
01762                               FALSE);
01763         }
01764         else
01765         {
01766             MdlPagesPtr = MmGetMdlPfnArray(Mdl);
01767             MdlPagesPtr += ((ULONG_PTR)CurrentVa - (ULONG_PTR)Mdl->StartVa) >> PAGE_SHIFT;
01768 
01769             PhysicalAddress.QuadPart = *MdlPagesPtr << PAGE_SHIFT;
01770             PhysicalAddress.QuadPart += BYTE_OFFSET(CurrentVa);
01771 
01772             HighestAcceptableAddress = HalpGetAdapterMaximumPhysicalAddress(AdapterObject);
01773             if ((PhysicalAddress.QuadPart + Length) > HighestAcceptableAddress.QuadPart)
01774             {
01775                 HalpCopyBufferMap(Mdl,
01776                                   RealMapRegisterBase,
01777                                   CurrentVa,
01778                                   Length,
01779                                   FALSE);
01780             }
01781         }
01782     }
01783 
01784     RealMapRegisterBase->Counter = 0;
01785 
01786     return TRUE;
01787 }
01788 
01820 PHYSICAL_ADDRESS
01821 NTAPI
01822 IoMapTransfer(IN PADAPTER_OBJECT AdapterObject,
01823               IN PMDL Mdl,
01824               IN PVOID MapRegisterBase,
01825               IN PVOID CurrentVa,
01826               IN OUT PULONG Length,
01827               IN BOOLEAN WriteToDevice)
01828 {
01829     PPFN_NUMBER MdlPagesPtr;
01830     PFN_NUMBER MdlPage1, MdlPage2;
01831     ULONG ByteOffset;
01832     ULONG TransferOffset;
01833     ULONG TransferLength;
01834     BOOLEAN UseMapRegisters;
01835     PROS_MAP_REGISTER_ENTRY RealMapRegisterBase;
01836     PHYSICAL_ADDRESS PhysicalAddress;
01837     PHYSICAL_ADDRESS HighestAcceptableAddress;
01838     ULONG Counter;
01839     DMA_MODE AdapterMode;
01840     KIRQL OldIrql;
01841 
01842     /*
01843      * Precalculate some values that are used in all cases.
01844      *
01845      * ByteOffset is offset inside the page at which the transfer starts.
01846      * MdlPagesPtr is pointer inside the MDL page chain at the page where the
01847      *             transfer start.
01848      * PhysicalAddress is physical address corresponding to the transfer
01849      *                 start page and offset.
01850      * TransferLength is the inital length of the transfer, which is reminder
01851      *                of the first page. The actual value is calculated below.
01852      *
01853      * Note that all the variables can change during the processing which
01854      * takes place below. These are just initial values.
01855      */
01856     ByteOffset = BYTE_OFFSET(CurrentVa);
01857 
01858     MdlPagesPtr = MmGetMdlPfnArray(Mdl);
01859     MdlPagesPtr += ((ULONG_PTR)CurrentVa - (ULONG_PTR)Mdl->StartVa) >> PAGE_SHIFT;
01860 
01861     PhysicalAddress.QuadPart = *MdlPagesPtr << PAGE_SHIFT;
01862     PhysicalAddress.QuadPart += ByteOffset;
01863 
01864     TransferLength = PAGE_SIZE - ByteOffset;
01865 
01866     /*
01867      * Special case for bus master adapters with S/G support. We can directly
01868      * use the buffer specified by the MDL, so not much work has to be done.
01869      *
01870      * Just return the passed VA's corresponding physical address and update
01871      * length to the number of physically contiguous bytes found. Also
01872      * pages crossing the 4Gb boundary aren't considered physically contiguous.
01873      */
01874     if (MapRegisterBase == NULL)
01875     {
01876         while (TransferLength < *Length)
01877         {
01878             MdlPage1 = *MdlPagesPtr;
01879             MdlPage2 = *(MdlPagesPtr + 1);
01880             if (MdlPage1 + 1 != MdlPage2) break;
01881             if ((MdlPage1 ^ MdlPage2) & ~0xFFFFF) break;
01882             TransferLength += PAGE_SIZE;
01883             MdlPagesPtr++;
01884         }
01885 
01886         if (TransferLength < *Length) *Length = TransferLength;
01887 
01888         return PhysicalAddress;
01889     }
01890 
01891     /*
01892      * The code below applies to slave DMA adapters and bus master adapters
01893      * without hardward S/G support.
01894      */
01895     RealMapRegisterBase = (PROS_MAP_REGISTER_ENTRY)((ULONG_PTR)MapRegisterBase & ~MAP_BASE_SW_SG);
01896 
01897     /*
01898      * Try to calculate the size of the transfer. We can only transfer
01899      * pages that are physically contiguous and that don't cross the
01900      * 64Kb boundary (this limitation applies only for ISA controllers).
01901      */
01902     while (TransferLength < *Length)
01903     {
01904         MdlPage1 = *MdlPagesPtr;
01905         MdlPage2 = *(MdlPagesPtr + 1);
01906         if (MdlPage1 + 1 != MdlPage2) break;
01907         if (!HalpEisaDma && ((MdlPage1 ^ MdlPage2) & ~0xF)) break;
01908         TransferLength += PAGE_SIZE;
01909         MdlPagesPtr++;
01910     }
01911 
01912     if (TransferLength > *Length) TransferLength = *Length;
01913 
01914     /*
01915      * If we're about to simulate software S/G and not all the pages are
01916      * physically contiguous then we must use the map registers to store
01917      * the data and allow the whole transfer to proceed at once.
01918      */
01919     if (((ULONG_PTR)MapRegisterBase & MAP_BASE_SW_SG) && (TransferLength < *Length))
01920     {
01921         UseMapRegisters = TRUE;
01922         PhysicalAddress = RealMapRegisterBase->PhysicalAddress;
01923         PhysicalAddress.QuadPart += ByteOffset;
01924         TransferLength = *Length;
01925         RealMapRegisterBase->Counter = MAXULONG;
01926         Counter = 0;
01927     }
01928     else
01929     {
01930         /*
01931          * This is ordinary DMA transfer, so just update the progress
01932          * counters. These are used by IoFlushAdapterBuffers to track
01933          * the transfer progress.
01934          */
01935         UseMapRegisters = FALSE;
01936         Counter = RealMapRegisterBase->Counter;
01937         RealMapRegisterBase->Counter += BYTES_TO_PAGES(ByteOffset + TransferLength);
01938 
01939         /*
01940          * Check if the buffer doesn't exceed the highest physical address
01941          * limit of the device. In that case we must use the map registers to
01942          * store the data.
01943          */
01944         HighestAcceptableAddress = HalpGetAdapterMaximumPhysicalAddress(AdapterObject);
01945         if ((PhysicalAddress.QuadPart + TransferLength) > HighestAcceptableAddress.QuadPart)
01946         {
01947             UseMapRegisters = TRUE;
01948             PhysicalAddress = RealMapRegisterBase[Counter].PhysicalAddress;
01949             PhysicalAddress.QuadPart += ByteOffset;
01950             if ((ULONG_PTR)MapRegisterBase & MAP_BASE_SW_SG)
01951             {
01952                 RealMapRegisterBase->Counter = MAXULONG;
01953                 Counter = 0;
01954             }
01955         }
01956     }
01957 
01958     /*
01959      * If we decided to use the map registers (see above) and we're about
01960      * to transfer data to the device then copy the buffers into the map
01961      * register memory.
01962      */
01963     if ((UseMapRegisters) && (WriteToDevice))
01964     {
01965         HalpCopyBufferMap(Mdl,
01966                           RealMapRegisterBase + Counter,
01967                           CurrentVa,
01968                           TransferLength,
01969                           WriteToDevice);
01970     }
01971 
01972     /*
01973      * Return the length of transfer that actually takes place.
01974      */
01975     *Length = TransferLength;
01976 
01977     /*
01978      * If we're doing slave (system) DMA then program the (E)ISA controller
01979      * to actually start the transfer.
01980      */
01981     if ((AdapterObject) && !(AdapterObject->MasterDevice))
01982     {
01983         AdapterMode = AdapterObject->AdapterMode;
01984 
01985         if (WriteToDevice)
01986         {
01987             AdapterMode.TransferType = WRITE_TRANSFER;
01988         }
01989         else
01990         {
01991             AdapterMode.TransferType = READ_TRANSFER;
01992             if (AdapterObject->IgnoreCount)
01993             {
01994                 RtlZeroMemory((PUCHAR)RealMapRegisterBase[Counter].VirtualAddress + ByteOffset,
01995                               TransferLength);
01996             }
01997         }
01998 
01999         TransferOffset = PhysicalAddress.LowPart & 0xFFFF;
02000         if (AdapterObject->Width16Bits)
02001         {
02002             TransferLength >>= 1;
02003             TransferOffset >>= 1;
02004         }
02005 
02006         KeAcquireSpinLock(&AdapterObject->MasterAdapter->SpinLock, &OldIrql);
02007 
02008         if (AdapterObject->AdapterNumber == 1)
02009         {
02010             PDMA1_CONTROL DmaControl1 = AdapterObject->AdapterBaseVa;
02011 
02012             /* Reset Register */
02013             WRITE_PORT_UCHAR(&DmaControl1->ClearBytePointer, 0);
02014 
02015             /* Set the Mode */
02016             WRITE_PORT_UCHAR(&DmaControl1->Mode, AdapterMode.Byte);
02017 
02018             /* Set the Offset Register */
02019             WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress,
02020                              (UCHAR)(TransferOffset));
02021             WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress,
02022                              (UCHAR)(TransferOffset >> 8));
02023 
02024             /* Set the Page Register */
02025             WRITE_PORT_UCHAR(AdapterObject->PagePort + FIELD_OFFSET(EISA_CONTROL, DmaController1Pages),
02026                              (UCHAR)(PhysicalAddress.LowPart >> 16));
02027             if (HalpEisaDma)
02028             {
02029                 WRITE_PORT_UCHAR(AdapterObject->PagePort + FIELD_OFFSET(EISA_CONTROL, DmaController2Pages),
02030                                  0);
02031             }
02032 
02033             /* Set the Length */
02034             WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount,
02035                              (UCHAR)(TransferLength - 1));
02036             WRITE_PORT_UCHAR(&DmaControl1->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount,
02037                              (UCHAR)((TransferLength - 1) >> 8));
02038 
02039             /* Unmask the Channel */
02040             WRITE_PORT_UCHAR(&DmaControl1->SingleMask, AdapterObject->ChannelNumber | DMA_CLEARMASK);
02041         }
02042         else
02043         {
02044             PDMA2_CONTROL DmaControl2 = AdapterObject->AdapterBaseVa;
02045 
02046             /* Reset Register */
02047             WRITE_PORT_UCHAR(&DmaControl2->ClearBytePointer, 0);
02048 
02049             /* Set the Mode */
02050             WRITE_PORT_UCHAR(&DmaControl2->Mode, AdapterMode.Byte);
02051 
02052             /* Set the Offset Register */
02053             WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress,
02054                              (UCHAR)(TransferOffset));
02055             WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseAddress,
02056                              (UCHAR)(TransferOffset >> 8));
02057 
02058             /* Set the Page Register */
02059             WRITE_PORT_UCHAR(AdapterObject->PagePort + FIELD_OFFSET(EISA_CONTROL, DmaController1Pages),
02060                              (UCHAR)(PhysicalAddress.u.LowPart >> 16));
02061             if (HalpEisaDma)
02062             {
02063                 WRITE_PORT_UCHAR(AdapterObject->PagePort + FIELD_OFFSET(EISA_CONTROL, DmaController2Pages),
02064                                  0);
02065             }
02066 
02067             /* Set the Length */
02068             WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount,
02069                              (UCHAR)(TransferLength - 1));
02070             WRITE_PORT_UCHAR(&DmaControl2->DmaAddressCount[AdapterObject->ChannelNumber].DmaBaseCount,
02071                              (UCHAR)((TransferLength - 1) >> 8));
02072 
02073             /* Unmask the Channel */
02074             WRITE_PORT_UCHAR(&DmaControl2->SingleMask,
02075                              AdapterObject->ChannelNumber | DMA_CLEARMASK);
02076         }
02077 
02078         KeReleaseSpinLock(&AdapterObject->MasterAdapter->SpinLock, OldIrql);
02079     }
02080 
02081     /*
02082      * Return physical address of the buffer with data that is used for the
02083      * transfer. It can either point inside the Mdl that was passed by the
02084      * caller or into the map registers if the Mdl buffer can't be used
02085      * directly.
02086      */
02087      return PhysicalAddress;
02088 }
02089 #endif
02090 
02096 BOOLEAN
02097 NTAPI
02098 HalFlushCommonBuffer(IN PADAPTER_OBJECT AdapterObject,
02099                      IN ULONG Length,
02100                      IN PHYSICAL_ADDRESS LogicalAddress,
02101                      IN PVOID VirtualAddress)
02102 {
02103     /* Function always returns true */
02104     return TRUE;
02105 }
02106 
02107 /*
02108  * @implemented
02109  */
02110 PVOID
02111 NTAPI
02112 HalAllocateCrashDumpRegisters(IN PADAPTER_OBJECT AdapterObject,
02113                               IN OUT PULONG NumberOfMapRegisters)
02114 {
02115     PADAPTER_OBJECT MasterAdapter = AdapterObject->MasterAdapter;
02116     ULONG MapRegisterNumber;
02117 
02118     /* Check if it needs map registers */
02119     if (AdapterObject->NeedsMapRegisters)
02120     {
02121         /* Check if we have enough */
02122         if (*NumberOfMapRegisters > AdapterObject->MapRegistersPerChannel)
02123         {
02124             /* We don't, fail */
02125             AdapterObject->NumberOfMapRegisters = 0;
02126             return NULL;
02127         }
02128 
02129         /* Try to find free map registers */
02130         MapRegisterNumber = RtlFindClearBitsAndSet(MasterAdapter->MapRegisters,
02131                                                    *NumberOfMapRegisters,
02132                                                    0);
02133 
02134         /* Check if nothing was found */
02135         if (MapRegisterNumber == MAXULONG)
02136         {
02137             /* No free registers found, so use the base registers */
02138             RtlSetBits(MasterAdapter->MapRegisters,
02139                        0,
02140                        *NumberOfMapRegisters);
02141             MapRegisterNumber = 0;
02142         }
02143 
02144         /* Calculate the new base */
02145         AdapterObject->MapRegisterBase =
02146             (PROS_MAP_REGISTER_ENTRY)(MasterAdapter->MapRegisterBase +
02147                                       MapRegisterNumber);
02148 
02149         /* Check if scatter gather isn't supported */
02150         if (!AdapterObject->ScatterGather)
02151         {
02152             /* Set the flag */
02153             AdapterObject->MapRegisterBase =
02154                 (PROS_MAP_REGISTER_ENTRY)
02155                 ((ULONG_PTR)AdapterObject->MapRegisterBase | MAP_BASE_SW_SG);
02156         }
02157     }
02158     else
02159     {
02160         AdapterObject->MapRegisterBase = NULL;
02161         AdapterObject->NumberOfMapRegisters = 0;
02162     }
02163 
02164     /* Return the base */
02165     return AdapterObject->MapRegisterBase;
02166 }
02167 
02168 /* EOF */

Generated on Sat May 26 2012 04:26:35 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.