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

io.c
Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:   See COPYING in the top level directory
00003  * PROJECT:     ReactOS NDIS library
00004  * FILE:        ndis/io.c
00005  * PURPOSE:     I/O related routines
00006  * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
00007  *              Vizzini (vizzini@plasmic.com)
00008  * REVISIONS:
00009  *   CSH 01/08-2000 Created
00010  *   20 Aug 2003 Vizzini - DMA support
00011  *   3  Oct 2003 Vizzini - Formatting and minor bugfixes
00012  */
00013 
00014 #include "ndissys.h"
00015 
00016 
00017 VOID NTAPI HandleDeferredProcessing(
00018     IN  PKDPC   Dpc,
00019     IN  PVOID   DeferredContext,
00020     IN  PVOID   SystemArgument1,
00021     IN  PVOID   SystemArgument2)
00022 /*
00023  * FUNCTION: Deferred interrupt processing routine
00024  * ARGUMENTS:
00025  *     Dpc             = Pointer to DPC object
00026  *     DeferredContext = Pointer to context information (LOGICAL_ADAPTER)
00027  *     SystemArgument1 = Unused
00028  *     SystemArgument2 = Unused
00029  */
00030 {
00031   PLOGICAL_ADAPTER Adapter = GET_LOGICAL_ADAPTER(DeferredContext);
00032 
00033   NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
00034 
00035   ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
00036 
00037   /* Call the deferred interrupt service handler for this adapter */
00038   (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.HandleInterruptHandler)(
00039       Adapter->NdisMiniportBlock.MiniportAdapterContext);
00040 
00041   /* re-enable the interrupt */
00042   NDIS_DbgPrint(MAX_TRACE, ("re-enabling the interrupt\n"));
00043   if(Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.EnableInterruptHandler)
00044     (*Adapter->NdisMiniportBlock.DriverHandle->MiniportCharacteristics.EnableInterruptHandler)(
00045         Adapter->NdisMiniportBlock.MiniportAdapterContext);
00046 
00047   NDIS_DbgPrint(MAX_TRACE, ("Leaving.\n"));
00048 }
00049 
00050 
00051 BOOLEAN NTAPI ServiceRoutine(
00052     IN  PKINTERRUPT Interrupt,
00053     IN  PVOID       ServiceContext)
00054 /*
00055  * FUNCTION: Interrupt service routine
00056  * ARGUMENTS:
00057  *     Interrupt      = Pointer to interrupt object
00058  *     ServiceContext = Pointer to context information (PNDIS_MINIPORT_INTERRUPT)
00059  * RETURNS
00060  *     TRUE if a miniport controlled device generated the interrupt
00061  */
00062 {
00063   BOOLEAN InterruptRecognized = FALSE;
00064   BOOLEAN QueueMiniportHandleInterrupt = FALSE;
00065   PNDIS_MINIPORT_INTERRUPT NdisInterrupt = ServiceContext;
00066   PNDIS_MINIPORT_BLOCK NdisMiniportBlock = NdisInterrupt->Miniport;
00067 
00068   NDIS_DbgPrint(MAX_TRACE, ("Called. Interrupt (0x%X)\n", NdisInterrupt));
00069 
00070   if (NdisInterrupt->IsrRequested) {
00071       NDIS_DbgPrint(MAX_TRACE, ("Calling MiniportISR\n"));
00072       (*NdisMiniportBlock->DriverHandle->MiniportCharacteristics.ISRHandler)(
00073           &InterruptRecognized,
00074           &QueueMiniportHandleInterrupt,
00075           NdisMiniportBlock->MiniportAdapterContext);
00076 
00077   } else if (NdisMiniportBlock->DriverHandle->MiniportCharacteristics.DisableInterruptHandler) {
00078       NDIS_DbgPrint(MAX_TRACE, ("Calling MiniportDisableInterrupt\n"));
00079       (*NdisMiniportBlock->DriverHandle->MiniportCharacteristics.DisableInterruptHandler)(
00080           NdisMiniportBlock->MiniportAdapterContext);
00081        QueueMiniportHandleInterrupt = TRUE;
00082        InterruptRecognized = TRUE;
00083   }
00084 
00085 
00086   if (QueueMiniportHandleInterrupt)
00087   {
00088       NDIS_DbgPrint(MAX_TRACE, ("Queuing DPC.\n"));
00089       KeInsertQueueDpc(&NdisInterrupt->InterruptDpc, NULL, NULL);
00090   }
00091 
00092   NDIS_DbgPrint(MAX_TRACE, ("Leaving.\n"));
00093 
00094   return InterruptRecognized;
00095 }
00096 
00097 
00098 /*
00099  * @implemented
00100  */
00101 VOID
00102 EXPORT
00103 NdisImmediateReadPortUchar(
00104     IN  NDIS_HANDLE WrapperConfigurationContext,
00105     IN  ULONG       Port,
00106     OUT PUCHAR      Data)
00107 {
00108   NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
00109   *Data = READ_PORT_UCHAR(UlongToPtr(Port)); // FIXME: What to do with WrapperConfigurationContext?
00110 }
00111 
00112 
00113 /*
00114  * @implemented
00115  */
00116 VOID
00117 EXPORT
00118 NdisImmediateReadPortUlong(
00119     IN  NDIS_HANDLE WrapperConfigurationContext,
00120     IN  ULONG       Port,
00121     OUT PULONG      Data)
00122 {
00123   NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
00124   *Data = READ_PORT_ULONG(UlongToPtr(Port)); // FIXME: What to do with WrapperConfigurationContext?
00125 }
00126 
00127 
00128 /*
00129  * @implemented
00130  */
00131 VOID
00132 EXPORT
00133 NdisImmediateReadPortUshort(
00134     IN  NDIS_HANDLE WrapperConfigurationContext,
00135     IN  ULONG       Port,
00136     OUT PUSHORT     Data)
00137 {
00138   NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
00139   *Data = READ_PORT_USHORT(UlongToPtr(Port)); // FIXME: What to do with WrapperConfigurationContext?
00140 }
00141 
00142 
00143 /*
00144  * @implemented
00145  */
00146 VOID
00147 EXPORT
00148 NdisImmediateWritePortUchar(
00149     IN  NDIS_HANDLE WrapperConfigurationContext,
00150     IN  ULONG       Port,
00151     IN  UCHAR       Data)
00152 {
00153   NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
00154   WRITE_PORT_UCHAR(UlongToPtr(Port), Data); // FIXME: What to do with WrapperConfigurationContext?
00155 }
00156 
00157 
00158 /*
00159  * @implemented
00160  */
00161 VOID
00162 EXPORT
00163 NdisImmediateWritePortUlong(
00164     IN  NDIS_HANDLE WrapperConfigurationContext,
00165     IN  ULONG       Port,
00166     IN  ULONG       Data)
00167 {
00168   NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
00169   WRITE_PORT_ULONG(UlongToPtr(Port), Data); // FIXME: What to do with WrapperConfigurationContext?
00170 }
00171 
00172 
00173 /*
00174  * @implemented
00175  */
00176 VOID
00177 EXPORT
00178 NdisImmediateWritePortUshort(
00179     IN  NDIS_HANDLE WrapperConfigurationContext,
00180     IN  ULONG       Port,
00181     IN  USHORT      Data)
00182 {
00183   NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
00184   WRITE_PORT_USHORT(UlongToPtr(Port), Data); // FIXME: What to do with WrapperConfigurationContext?
00185 }
00186 
00187 IO_ALLOCATION_ACTION NTAPI NdisSubordinateMapRegisterCallback (
00188     IN PDEVICE_OBJECT  DeviceObject,
00189     IN PIRP            Irp,
00190     IN PVOID           MapRegisterBase,
00191     IN PVOID           Context)
00192 /*
00193  * FUNCTION: Called back during reservation of map registers
00194  * ARGUMENTS:
00195  *     DeviceObject: Device object of the deivce setting up DMA
00196  *     Irp: Reserved; must be ignored
00197  *     MapRegisterBase: Map registers assigned for transfer
00198  *     Context: LOGICAL_ADAPTER object of the requesting miniport
00199  * NOTES:
00200  *     - Called at IRQL = DISPATCH_LEVEL
00201  */
00202 {
00203     PNDIS_DMA_BLOCK DmaBlock = Context;
00204     
00205     NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
00206     
00207     DmaBlock->MapRegisterBase = MapRegisterBase;
00208     
00209     NDIS_DbgPrint(MAX_TRACE, ("setting event and leaving.\n"));
00210     
00211     KeSetEvent(&DmaBlock->AllocationEvent, 0, FALSE);
00212     
00213     /* We have to hold the object open to keep our lock on the system DMA controller */
00214     return KeepObject;
00215 }
00216 IO_ALLOCATION_ACTION NTAPI NdisBusMasterMapRegisterCallback (
00217     IN PDEVICE_OBJECT  DeviceObject,
00218     IN PIRP            Irp,
00219     IN PVOID           MapRegisterBase,
00220     IN PVOID           Context)
00221 /*
00222  * FUNCTION: Called back during reservation of map registers
00223  * ARGUMENTS:
00224  *     DeviceObject: Device object of the deivce setting up DMA
00225  *     Irp: Reserved; must be ignored
00226  *     MapRegisterBase: Map registers assigned for transfer
00227  *     Context: LOGICAL_ADAPTER object of the requesting miniport
00228  * NOTES:
00229  *     - Called once per BaseMapRegister (see NdisMAllocateMapRegisters)
00230  *     - Called at IRQL = DISPATCH_LEVEL
00231  */
00232 {
00233   PLOGICAL_ADAPTER Adapter = Context;
00234 
00235   NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
00236 
00237   Adapter->NdisMiniportBlock.MapRegisters[Adapter->NdisMiniportBlock.CurrentMapRegister].MapRegister = MapRegisterBase;
00238 
00239   NDIS_DbgPrint(MAX_TRACE, ("setting event and leaving.\n"));
00240 
00241   KeSetEvent(Adapter->NdisMiniportBlock.AllocationEvent, 0, FALSE);
00242 
00243   /* We're a bus master so we can go ahead and deallocate the object now */
00244   return DeallocateObjectKeepRegisters;
00245 }
00246 /*
00247  * @implemented
00248  */
00249 NDIS_STATUS
00250 EXPORT
00251 NdisMAllocateMapRegisters(
00252     IN  NDIS_HANDLE   MiniportAdapterHandle,
00253     IN  UINT          DmaChannel,
00254     IN  NDIS_DMA_SIZE DmaSize,
00255     IN  ULONG         BaseMapRegistersNeeded,
00256     IN  ULONG         MaximumBufferSize)
00257 /*
00258  * FUNCTION: Allocate map registers for use in DMA transfers
00259  * ARGUMENTS:
00260  *     MiniportAdapterHandle: Passed in to MiniportInitialize
00261  *     DmaChannel: DMA channel to use
00262  *     DmaSize: bit width of DMA transfers
00263  *     BaseMapRegistersNeeded: number of base map registers requested
00264  *     MaximumBufferSize: largest single buffer transferred
00265  * RETURNS:
00266  *     NDIS_STATUS_SUCCESS on success
00267  *     NDIS_STATUS_RESOURCES on failure
00268  * NOTES:
00269  *     - the win2k ddk and the nt4 ddk have conflicting prototypes for this.
00270  *       I'm implementing the 2k one.
00271  *     - do not confuse a "base map register" with a "map register" - they
00272  *       are different.  Only NDIS seems to use the base concept.  The idea
00273  *       is that a miniport supplies the number of base map registers it will
00274  *       need, which is equal to the number of DMA send buffers it manages.
00275  *       NDIS then allocates a number of map registers to go with each base
00276  *       map register, so that a driver just has to send the base map register
00277  *       number during dma operations and NDIS can find the group of real
00278  *       map registers that represent the transfer.
00279  *     - Because of the above sillyness, you can only specify a few base map
00280  *       registers at most.  a 1514-byte packet is two map registers at 4k
00281  *       page size.
00282  *     - NDIS limits the total number of allocated map registers to 64,
00283  *       which (in the case of the above example) limits the number of base
00284  *       map registers to 32.
00285  */
00286 {
00287   DEVICE_DESCRIPTION   Description;
00288   PDMA_ADAPTER         AdapterObject = 0;
00289   UINT                 MapRegistersPerBaseRegister = 0;
00290   ULONG                AvailableMapRegisters;
00291   NTSTATUS             NtStatus;
00292   PLOGICAL_ADAPTER     Adapter;
00293   PDEVICE_OBJECT       DeviceObject = 0;
00294   KEVENT               AllocationEvent;
00295   KIRQL                OldIrql;
00296 
00297   NDIS_DbgPrint(MAX_TRACE, ("called: Handle 0x%x, DmaChannel 0x%x, DmaSize 0x%x, BaseMapRegsNeeded: 0x%x, MaxBuffer: 0x%x.\n",
00298                             MiniportAdapterHandle, DmaChannel, DmaSize, BaseMapRegistersNeeded, MaximumBufferSize));
00299 
00300   memset(&Description,0,sizeof(Description));
00301 
00302   Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle;
00303 
00304   ASSERT(Adapter);
00305 
00306   /* only bus masters may call this routine */
00307   if(!(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_BUS_MASTER)) {
00308     NDIS_DbgPrint(MIN_TRACE, ("Not a bus master\n"));
00309     return NDIS_STATUS_NOT_SUPPORTED;
00310   }
00311 
00312   DeviceObject = Adapter->NdisMiniportBlock.DeviceObject;
00313 
00314   KeInitializeEvent(&AllocationEvent, NotificationEvent, FALSE);
00315   Adapter->NdisMiniportBlock.AllocationEvent = &AllocationEvent;
00316 
00317   /*
00318   * map registers correlate to physical pages.  ndis documents a
00319   * maximum of 64 map registers that it will return.
00320   * at 4k pages, a 1514-byte buffer can span not more than 2 pages.
00321   *
00322   * the number of registers required for a given physical mapping
00323   * is (first register + last register + one per page size),
00324   * given that physical mapping is > 2.
00325   */
00326 
00327   /* unhandled corner case: {1,2}-byte max buffer size */
00328   ASSERT(MaximumBufferSize > 2);
00329   MapRegistersPerBaseRegister = ((MaximumBufferSize-2) / (2*PAGE_SIZE)) + 2;
00330 
00331   Description.Version = DEVICE_DESCRIPTION_VERSION;
00332   Description.Master = TRUE;                         /* implied by calling this function */
00333   Description.ScatterGather = TRUE;                  /* XXX UNTRUE: All BM DMA are S/G (ms seems to do this) */
00334   Description.BusNumber = Adapter->NdisMiniportBlock.BusNumber;
00335   Description.InterfaceType = Adapter->NdisMiniportBlock.BusType;
00336   Description.DmaChannel = DmaChannel;
00337   Description.MaximumLength = MaximumBufferSize;
00338   
00339   if(DmaSize == NDIS_DMA_64BITS)
00340     Description.Dma64BitAddresses = TRUE;
00341   else if(DmaSize == NDIS_DMA_32BITS)
00342     Description.Dma32BitAddresses = TRUE;
00343 
00344   AdapterObject = IoGetDmaAdapter(
00345     Adapter->NdisMiniportBlock.PhysicalDeviceObject, &Description, &AvailableMapRegisters);
00346 
00347   if(!AdapterObject)
00348     {
00349       NDIS_DbgPrint(MIN_TRACE, ("Unable to allocate an adapter object; bailing out\n"));
00350       return NDIS_STATUS_RESOURCES;
00351     }
00352 
00353   Adapter->NdisMiniportBlock.SystemAdapterObject = AdapterObject;
00354 
00355   if(AvailableMapRegisters < MapRegistersPerBaseRegister)
00356     {
00357       NDIS_DbgPrint(MIN_TRACE, ("Didn't get enough map registers from hal - requested 0x%x, got 0x%x\n",
00358           MapRegistersPerBaseRegister, AvailableMapRegisters));
00359 
00360       AdapterObject->DmaOperations->PutDmaAdapter(AdapterObject);
00361       Adapter->NdisMiniportBlock.SystemAdapterObject = NULL;
00362       return NDIS_STATUS_RESOURCES;
00363     }
00364 
00365   /* allocate & zero space in the miniport block for the registers */
00366   Adapter->NdisMiniportBlock.MapRegisters = ExAllocatePool(NonPagedPool, BaseMapRegistersNeeded * sizeof(MAP_REGISTER_ENTRY));
00367   if(!Adapter->NdisMiniportBlock.MapRegisters)
00368     {
00369       NDIS_DbgPrint(MIN_TRACE, ("insufficient resources.\n"));
00370       AdapterObject->DmaOperations->PutDmaAdapter(AdapterObject);
00371       Adapter->NdisMiniportBlock.SystemAdapterObject = NULL;
00372       return NDIS_STATUS_RESOURCES;
00373     }
00374 
00375   memset(Adapter->NdisMiniportBlock.MapRegisters, 0, BaseMapRegistersNeeded * sizeof(MAP_REGISTER_ENTRY));
00376   Adapter->NdisMiniportBlock.BaseMapRegistersNeeded = (USHORT)BaseMapRegistersNeeded;
00377 
00378   while(BaseMapRegistersNeeded)
00379     {
00380       NDIS_DbgPrint(MAX_TRACE, ("iterating, basemapregistersneeded = %d\n", BaseMapRegistersNeeded));
00381 
00382       BaseMapRegistersNeeded--;
00383       Adapter->NdisMiniportBlock.CurrentMapRegister = (USHORT)BaseMapRegistersNeeded;
00384       KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
00385         {
00386           NtStatus = AdapterObject->DmaOperations->AllocateAdapterChannel(
00387               AdapterObject, DeviceObject, MapRegistersPerBaseRegister,
00388               NdisBusMasterMapRegisterCallback, Adapter);
00389         }
00390       KeLowerIrql(OldIrql);
00391 
00392       if(!NT_SUCCESS(NtStatus))
00393         {
00394           NDIS_DbgPrint(MIN_TRACE, ("IoAllocateAdapterChannel failed: 0x%x\n", NtStatus));
00395           ExFreePool(Adapter->NdisMiniportBlock.MapRegisters);
00396           AdapterObject->DmaOperations->PutDmaAdapter(AdapterObject);
00397           Adapter->NdisMiniportBlock.CurrentMapRegister = Adapter->NdisMiniportBlock.BaseMapRegistersNeeded = 0;
00398           Adapter->NdisMiniportBlock.SystemAdapterObject = NULL;
00399           return NDIS_STATUS_RESOURCES;
00400         }
00401 
00402       NDIS_DbgPrint(MAX_TRACE, ("waiting on event\n"));
00403 
00404       NtStatus = KeWaitForSingleObject(&AllocationEvent, Executive, KernelMode, FALSE, 0);
00405 
00406       if(!NT_SUCCESS(NtStatus))
00407         {
00408           NDIS_DbgPrint(MIN_TRACE, ("KeWaitForSingleObject failed: 0x%x\n", NtStatus));
00409           ExFreePool(Adapter->NdisMiniportBlock.MapRegisters);
00410           AdapterObject->DmaOperations->PutDmaAdapter(AdapterObject);
00411           Adapter->NdisMiniportBlock.CurrentMapRegister = Adapter->NdisMiniportBlock.BaseMapRegistersNeeded = 0;
00412           Adapter->NdisMiniportBlock.SystemAdapterObject = NULL;
00413           return NDIS_STATUS_RESOURCES;
00414         }
00415 
00416       NDIS_DbgPrint(MAX_TRACE, ("resetting event\n"));
00417 
00418       KeResetEvent(&AllocationEvent);
00419     }
00420 
00421   NDIS_DbgPrint(MAX_TRACE, ("returning success\n"));
00422   return NDIS_STATUS_SUCCESS;
00423 }
00424 
00425 
00426 /*
00427  * @implemented
00428  */
00429 VOID
00430 EXPORT
00431 NdisMSetupDmaTransfer(OUT PNDIS_STATUS Status,
00432                       IN NDIS_HANDLE MiniportDmaHandle,
00433                       IN PNDIS_BUFFER Buffer,
00434                       IN ULONG Offset,
00435                       IN ULONG Length,
00436                       IN BOOLEAN WriteToDevice)
00437 {
00438     PNDIS_DMA_BLOCK DmaBlock = MiniportDmaHandle;
00439     NTSTATUS NtStatus;
00440     PLOGICAL_ADAPTER Adapter;
00441     KIRQL OldIrql;
00442     PDMA_ADAPTER AdapterObject;
00443     ULONG MapRegistersNeeded;
00444     
00445     NDIS_DbgPrint(MAX_TRACE, ("called: Handle 0x%x, Buffer 0x%x, Offset 0x%x, Length 0x%x, WriteToDevice 0x%x\n",
00446                               MiniportDmaHandle, Buffer, Offset, Length, WriteToDevice));
00447     
00448     Adapter = (PLOGICAL_ADAPTER)DmaBlock->Miniport;
00449     AdapterObject = (PDMA_ADAPTER)DmaBlock->SystemAdapterObject;
00450     
00451     MapRegistersNeeded = (Length + (PAGE_SIZE - 1)) / PAGE_SIZE;
00452     
00453     KeFlushIoBuffers(Buffer, !WriteToDevice, TRUE);
00454 
00455     KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
00456     {
00457         NtStatus = AdapterObject->DmaOperations->AllocateAdapterChannel(AdapterObject,
00458                                                                         Adapter->NdisMiniportBlock.PhysicalDeviceObject,
00459                                                                         MapRegistersNeeded,
00460                                                                         NdisSubordinateMapRegisterCallback, Adapter);
00461     }
00462     KeLowerIrql(OldIrql);
00463         
00464     if(!NT_SUCCESS(NtStatus))
00465     {
00466         NDIS_DbgPrint(MIN_TRACE, ("AllocateAdapterChannel failed: 0x%x\n", NtStatus));
00467         AdapterObject->DmaOperations->FreeAdapterChannel(AdapterObject);
00468         *Status = NDIS_STATUS_RESOURCES;
00469         return;
00470     }
00471     
00472     NtStatus = KeWaitForSingleObject(&DmaBlock->AllocationEvent, Executive, KernelMode, FALSE, 0);
00473         
00474     if(!NT_SUCCESS(NtStatus))
00475     {
00476         NDIS_DbgPrint(MIN_TRACE, ("KeWaitForSingleObject failed: 0x%x\n", NtStatus));
00477         AdapterObject->DmaOperations->FreeAdapterChannel(AdapterObject);
00478         *Status = NDIS_STATUS_RESOURCES;
00479         return;
00480     }
00481     
00482     /* We must throw away the return value of MapTransfer for a system DMA device */
00483     AdapterObject->DmaOperations->MapTransfer(AdapterObject, Buffer,
00484                                               DmaBlock->MapRegisterBase,
00485                                               (PUCHAR)MmGetMdlVirtualAddress(Buffer) + Offset, &Length, WriteToDevice);
00486     
00487     NDIS_DbgPrint(MAX_TRACE, ("returning success\n"));
00488     *Status = NDIS_STATUS_SUCCESS;
00489 }
00490 
00491 /*
00492  * @implemented
00493  */
00494 VOID
00495 EXPORT
00496 NdisSetupDmaTransfer(OUT PNDIS_STATUS    Status,
00497                      IN  PNDIS_HANDLE    NdisDmaHandle,
00498                      IN  PNDIS_BUFFER    Buffer,
00499                      IN  ULONG           Offset,
00500                      IN  ULONG           Length,
00501                      IN  BOOLEAN         WriteToDevice)
00502 /*
00503  * FUNCTION:
00504  * ARGUMENTS:
00505  * NOTES:
00506  *    NDIS 4.0
00507  */
00508 {
00509     NdisMSetupDmaTransfer(Status,
00510                           NdisDmaHandle,
00511                           Buffer,
00512                           Offset,
00513                           Length,
00514                           WriteToDevice);
00515 }
00516 
00517 /*
00518  * @implemented
00519  */
00520 VOID
00521 EXPORT
00522 NdisMCompleteDmaTransfer(OUT PNDIS_STATUS Status,
00523                          IN NDIS_HANDLE MiniportDmaHandle,
00524                          IN PNDIS_BUFFER Buffer,
00525                          IN ULONG Offset,
00526                          IN ULONG Length,
00527                          IN BOOLEAN WriteToDevice)
00528 {
00529     PNDIS_DMA_BLOCK DmaBlock = MiniportDmaHandle;
00530     PDMA_ADAPTER AdapterObject = (PDMA_ADAPTER)DmaBlock->SystemAdapterObject;
00531     
00532     NDIS_DbgPrint(MAX_TRACE, ("called: Handle 0x%x, Buffer 0x%x, Offset 0x%x, Length 0x%x, WriteToDevice 0x%x\n",
00533                               MiniportDmaHandle, Buffer, Offset, Length, WriteToDevice));
00534     
00535     if (!AdapterObject->DmaOperations->FlushAdapterBuffers(AdapterObject,
00536                                                            Buffer,
00537                                                            DmaBlock->MapRegisterBase,
00538                                                            (PUCHAR)MmGetMdlVirtualAddress(Buffer) + Offset,
00539                                                            Length,
00540                                                            WriteToDevice))
00541     {
00542         NDIS_DbgPrint(MIN_TRACE, ("FlushAdapterBuffers failed\n"));
00543         *Status = NDIS_STATUS_FAILURE;
00544         return;
00545     }
00546 
00547     AdapterObject->DmaOperations->FreeAdapterChannel(AdapterObject);
00548     
00549     NDIS_DbgPrint(MAX_TRACE, ("returning success\n"));
00550     *Status = NDIS_STATUS_SUCCESS;
00551 }
00552 
00553 /*
00554  * @implemented
00555  */
00556 VOID
00557 EXPORT
00558 NdisCompleteDmaTransfer(OUT PNDIS_STATUS    Status,
00559                         IN  PNDIS_HANDLE    NdisDmaHandle,
00560                         IN  PNDIS_BUFFER    Buffer,
00561                         IN  ULONG           Offset,
00562                         IN  ULONG           Length,
00563                         IN  BOOLEAN         WriteToDevice)
00564 {
00565     NdisMCompleteDmaTransfer(Status,
00566                              NdisDmaHandle,
00567                              Buffer,
00568                              Offset,
00569                              Length,
00570                              WriteToDevice);
00571 }
00572 
00573 /*
00574  * @implemented
00575  */
00576 VOID
00577 EXPORT
00578 NdisMStartBufferPhysicalMapping(
00579     IN  NDIS_HANDLE                 MiniportAdapterHandle,
00580     IN  PNDIS_BUFFER                Buffer,
00581     IN  ULONG                       PhysicalMapRegister,
00582     IN  BOOLEAN                     WriteToDevice,
00583     OUT PNDIS_PHYSICAL_ADDRESS_UNIT PhysicalAddressArray,
00584     OUT PUINT                       ArraySize)
00585 /*
00586  * FUNCTION: Sets up map registers for a bus-master DMA transfer
00587  * ARGUMENTS:
00588  *     MiniportAdapterHandle: handle originally input to MiniportInitialize
00589  *     Buffer: data to be transferred
00590  *     PhysicalMapRegister: specifies the map register to set up
00591  *     WriteToDevice: if true, data is being written to the device; else it is being read
00592  *     PhysicalAddressArray: list of mapped ranges suitable for DMA with the device
00593  *     ArraySize: number of elements in PhysicalAddressArray
00594  * NOTES:
00595  *     - Must be called at IRQL <= DISPATCH_LEVEL
00596  *     - The basic idea:  call IoMapTransfer() in a loop as many times as it takes
00597  *       in order to map all of the virtual memory to physical memoroy readable
00598  *       by the device
00599  *     - The caller supplies storage for the physical address array.
00600  */
00601 {
00602   PLOGICAL_ADAPTER Adapter;
00603   PVOID CurrentVa;
00604   ULONG TotalLength;
00605   PHYSICAL_ADDRESS ReturnedAddress;
00606   UINT LoopCount =  0;
00607 
00608   ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
00609   ASSERT(MiniportAdapterHandle && Buffer && PhysicalAddressArray && ArraySize);
00610 
00611   Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle;
00612   CurrentVa = MmGetMdlVirtualAddress(Buffer);
00613   TotalLength = MmGetMdlByteCount(Buffer);
00614 
00615   while(TotalLength)
00616     {
00617       ULONG Length = TotalLength;
00618 
00619       ReturnedAddress = Adapter->NdisMiniportBlock.SystemAdapterObject->DmaOperations->MapTransfer(
00620           Adapter->NdisMiniportBlock.SystemAdapterObject, Buffer,
00621           Adapter->NdisMiniportBlock.MapRegisters[PhysicalMapRegister].MapRegister,
00622           CurrentVa, &Length, WriteToDevice);
00623 
00624       Adapter->NdisMiniportBlock.MapRegisters[PhysicalMapRegister].WriteToDevice = WriteToDevice;
00625 
00626       PhysicalAddressArray[LoopCount].PhysicalAddress = ReturnedAddress;
00627       PhysicalAddressArray[LoopCount].Length = Length;
00628 
00629       TotalLength -= Length;
00630       CurrentVa = (PVOID)((ULONG_PTR)CurrentVa + Length);
00631 
00632       LoopCount++;
00633     }
00634 
00635   *ArraySize = LoopCount;
00636 }
00637 
00638 
00639 /*
00640  * @implemented
00641  */
00642 VOID
00643 EXPORT
00644 NdisMCompleteBufferPhysicalMapping(
00645     IN  NDIS_HANDLE     MiniportAdapterHandle,
00646     IN  PNDIS_BUFFER    Buffer,
00647     IN  ULONG           PhysicalMapRegister)
00648 /*
00649  * FUNCTION: Complete dma action started by NdisMStartBufferPhysicalMapping
00650  * ARGUMENTS:
00651  *     - MiniportAdapterHandle: handle originally input to MiniportInitialize
00652  *     - Buffer: NDIS_BUFFER to complete the mapping on
00653  *     - PhyscialMapRegister: the chosen map register
00654  * NOTES:
00655  *     - May be called at IRQL <= DISPATCH_LEVEL
00656  */
00657 {
00658   PLOGICAL_ADAPTER Adapter;
00659   VOID *CurrentVa;
00660   ULONG Length;
00661 
00662   ASSERT(KeGetCurrentIrql() <= DISPATCH_LEVEL);
00663   ASSERT(MiniportAdapterHandle && Buffer);
00664 
00665   Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle;
00666   CurrentVa = MmGetMdlVirtualAddress(Buffer);
00667   Length = MmGetMdlByteCount(Buffer);
00668 
00669   Adapter->NdisMiniportBlock.SystemAdapterObject->DmaOperations->FlushAdapterBuffers(
00670       Adapter->NdisMiniportBlock.SystemAdapterObject, Buffer,
00671       Adapter->NdisMiniportBlock.MapRegisters[PhysicalMapRegister].MapRegister,
00672       CurrentVa, Length,
00673       Adapter->NdisMiniportBlock.MapRegisters[PhysicalMapRegister].WriteToDevice);
00674 }
00675 
00676 
00677 /*
00678  * @implemented
00679  */
00680 VOID
00681 EXPORT
00682 NdisMDeregisterDmaChannel(
00683     IN  NDIS_HANDLE    MiniportDmaHandle)
00684 {
00685     PNDIS_DMA_BLOCK DmaBlock = MiniportDmaHandle;
00686     PDMA_ADAPTER AdapterObject = (PDMA_ADAPTER)DmaBlock->SystemAdapterObject;
00687 
00688     if (AdapterObject == ((PLOGICAL_ADAPTER)DmaBlock->Miniport)->NdisMiniportBlock.SystemAdapterObject)
00689         ((PLOGICAL_ADAPTER)DmaBlock->Miniport)->NdisMiniportBlock.SystemAdapterObject = NULL;
00690 
00691     AdapterObject->DmaOperations->PutDmaAdapter(AdapterObject);
00692 
00693     ExFreePool(DmaBlock);
00694 }
00695 
00696 
00697 /*
00698  * @implemented
00699  */
00700 VOID
00701 EXPORT
00702 NdisMDeregisterInterrupt(
00703     IN  PNDIS_MINIPORT_INTERRUPT    Interrupt)
00704 /*
00705  * FUNCTION: Releases an interrupt vector
00706  * ARGUMENTS:
00707  *     Interrupt = Pointer to interrupt object
00708  */
00709 {
00710     NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
00711     IoDisconnectInterrupt(Interrupt->InterruptObject);
00712     Interrupt->Miniport->RegisteredInterrupts--;
00713 
00714     if (Interrupt->Miniport->Interrupt == Interrupt)
00715         Interrupt->Miniport->Interrupt = NULL;
00716 }
00717 
00718 
00719 /*
00720  * @implemented
00721  */
00722 VOID
00723 EXPORT
00724 NdisMFreeMapRegisters(
00725     IN  NDIS_HANDLE MiniportAdapterHandle)
00726 /*
00727  * FUNCTION: Free previously allocated map registers
00728  * ARGUMENTS:
00729  *     MiniportAdapterHandle:  Handle originally passed in to MiniportInitialize
00730  * NOTES:
00731  */
00732 {
00733   KIRQL                OldIrql;
00734   PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle;
00735   PDMA_ADAPTER         AdapterObject;
00736   UINT                 MapRegistersPerBaseRegister;
00737   UINT                 i;
00738 
00739   NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
00740 
00741   ASSERT(Adapter);
00742 
00743   /* only bus masters may call this routine */
00744   if(!(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_BUS_MASTER) ||
00745      Adapter->NdisMiniportBlock.SystemAdapterObject == NULL) {
00746      NDIS_DbgPrint(MIN_TRACE, ("Not bus master or bad adapter object\n"));
00747     return;
00748   }
00749 
00750   MapRegistersPerBaseRegister = ((Adapter->NdisMiniportBlock.MaximumPhysicalMapping - 2) / PAGE_SIZE) + 2;
00751 
00752   AdapterObject = Adapter->NdisMiniportBlock.SystemAdapterObject;
00753 
00754   KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
00755     {
00756       for(i = 0; i < Adapter->NdisMiniportBlock.BaseMapRegistersNeeded; i++)
00757         {
00758           AdapterObject->DmaOperations->FreeMapRegisters(
00759               Adapter->NdisMiniportBlock.SystemAdapterObject,
00760               Adapter->NdisMiniportBlock.MapRegisters[i].MapRegister,
00761               MapRegistersPerBaseRegister);
00762         }
00763     }
00764  KeLowerIrql(OldIrql);
00765 
00766  AdapterObject->DmaOperations->PutDmaAdapter(AdapterObject);
00767  Adapter->NdisMiniportBlock.SystemAdapterObject = NULL;
00768 
00769  ExFreePool(Adapter->NdisMiniportBlock.MapRegisters);
00770 }
00771 
00772 
00773 /*
00774  * @implemented
00775  */
00776 NDIS_STATUS
00777 EXPORT
00778 NdisMMapIoSpace(
00779     OUT PVOID                   *VirtualAddress,
00780     IN  NDIS_HANDLE             MiniportAdapterHandle,
00781     IN  NDIS_PHYSICAL_ADDRESS   PhysicalAddress,
00782     IN  UINT                    Length)
00783 /*
00784  * FUNCTION: Maps a bus-relative address to a system-wide virtual address
00785  * ARGUMENTS:
00786  *     VirtualAddress: receives virtual address of mapping
00787  *     MiniportAdapterHandle: Handle originally input to MiniportInitialize
00788  *     PhysicalAddress: bus-relative address to map
00789  *     Length: Number of bytes to map
00790  * RETURNS:
00791  *     NDIS_STATUS_SUCCESS: the operation completed successfully
00792  *     NDIS_STATUS_RESOURCE_CONFLICT: the physical address range is already claimed
00793  *     NDIS_STATUS_RESOURCES: insufficient resources to complete the mapping
00794  *     NDIS_STATUS_FAILURE: a general failure has occured
00795  * NOTES:
00796  *     - Must be called at IRQL = PASSIVE_LEVEL
00797  */
00798 {
00799   PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle;
00800   ULONG AddressSpace = 0; /* Memory Space */
00801   NDIS_PHYSICAL_ADDRESS TranslatedAddress;
00802 
00803   PAGED_CODE();
00804   ASSERT(VirtualAddress && MiniportAdapterHandle);
00805 
00806   NDIS_DbgPrint(MAX_TRACE, ("Called\n"));
00807 
00808   if(!HalTranslateBusAddress(Adapter->NdisMiniportBlock.BusType, Adapter->NdisMiniportBlock.BusNumber,
00809                              PhysicalAddress, &AddressSpace, &TranslatedAddress))
00810   {
00811       NDIS_DbgPrint(MIN_TRACE, ("Unable to translate address\n"));
00812       return NDIS_STATUS_RESOURCES;
00813   }
00814 
00815   *VirtualAddress = MmMapIoSpace(TranslatedAddress, Length, MmNonCached);
00816 
00817   if(!*VirtualAddress) {
00818     NDIS_DbgPrint(MIN_TRACE, ("MmMapIoSpace failed\n"));
00819     return NDIS_STATUS_RESOURCES;
00820   }
00821 
00822   return NDIS_STATUS_SUCCESS;
00823 }
00824 
00825 
00826 /*
00827  * @implemented
00828  */
00829 ULONG
00830 EXPORT
00831 NdisMReadDmaCounter(
00832     IN  NDIS_HANDLE MiniportDmaHandle)
00833 {
00834   /* NOTE: Unlike NdisMGetDmaAlignment() below, this is a handle to the DMA block */
00835   PNDIS_DMA_BLOCK DmaBlock = MiniportDmaHandle;
00836   PDMA_ADAPTER AdapterObject = (PDMA_ADAPTER)DmaBlock->SystemAdapterObject;
00837 
00838   NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
00839 
00840   return AdapterObject->DmaOperations->ReadDmaCounter(AdapterObject);
00841 }
00842 
00843 
00844 /*
00845  * @implemented
00846  */
00847 ULONG
00848 EXPORT
00849 NdisMGetDmaAlignment(
00850     IN  NDIS_HANDLE MiniportAdapterHandle)
00851 {
00852   /* NOTE: Unlike NdisMReadDmaCounter() above, this is a handle to the NDIS miniport block */
00853   PLOGICAL_ADAPTER Adapter = MiniportAdapterHandle;
00854   PDMA_ADAPTER AdapterObject = (PDMA_ADAPTER)Adapter->NdisMiniportBlock.SystemAdapterObject;
00855 
00856   NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
00857 
00858   return AdapterObject->DmaOperations->GetDmaAlignment(AdapterObject);
00859 }
00860 
00861 
00862 /*
00863  * @implemented
00864  */
00865 NDIS_STATUS
00866 EXPORT
00867 NdisMRegisterDmaChannel(
00868     OUT PNDIS_HANDLE            MiniportDmaHandle,
00869     IN  NDIS_HANDLE             MiniportAdapterHandle,
00870     IN  UINT                    DmaChannel,
00871     IN  BOOLEAN                 Dma32BitAddresses,
00872     IN  PNDIS_DMA_DESCRIPTION   DmaDescription,
00873     IN  ULONG                   MaximumLength)
00874 {
00875   PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle;
00876   DEVICE_DESCRIPTION DeviceDesc;
00877   ULONG MapRegisters;
00878   PNDIS_DMA_BLOCK DmaBlock;
00879 
00880   NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
00881 
00882   RtlZeroMemory(&DeviceDesc, sizeof(DEVICE_DESCRIPTION));
00883 
00884   DeviceDesc.Version = DEVICE_DESCRIPTION_VERSION;
00885   DeviceDesc.Master = (Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_BUS_MASTER);
00886   DeviceDesc.ScatterGather = FALSE;
00887   DeviceDesc.DemandMode = DmaDescription->DemandMode;
00888   DeviceDesc.AutoInitialize = DmaDescription->AutoInitialize;
00889   DeviceDesc.Dma32BitAddresses = Dma32BitAddresses;
00890   DeviceDesc.Dma64BitAddresses = FALSE;
00891   DeviceDesc.BusNumber = Adapter->NdisMiniportBlock.BusNumber;
00892   DeviceDesc.DmaChannel = DmaDescription->DmaChannel;
00893   DeviceDesc.InterfaceType = Adapter->NdisMiniportBlock.BusType;
00894   DeviceDesc.DmaWidth = DmaDescription->DmaWidth;
00895   DeviceDesc.DmaSpeed = DmaDescription->DmaSpeed;
00896   DeviceDesc.MaximumLength = MaximumLength;
00897 
00898 
00899   DmaBlock = ExAllocatePool(NonPagedPool, sizeof(NDIS_DMA_BLOCK));
00900   if (!DmaBlock) {
00901       NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
00902       return NDIS_STATUS_RESOURCES;
00903   }
00904 
00905   DmaBlock->SystemAdapterObject = (PVOID)IoGetDmaAdapter(Adapter->NdisMiniportBlock.PhysicalDeviceObject, &DeviceDesc, &MapRegisters);
00906 
00907   if (!DmaBlock->SystemAdapterObject) {
00908       NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources\n"));
00909       ExFreePool(DmaBlock);
00910       return NDIS_STATUS_RESOURCES;
00911   }
00912 
00913   Adapter->NdisMiniportBlock.SystemAdapterObject = (PDMA_ADAPTER)DmaBlock->SystemAdapterObject;
00914     
00915   KeInitializeEvent(&DmaBlock->AllocationEvent, NotificationEvent, FALSE);
00916 
00917   DmaBlock->Miniport = Adapter;
00918 
00919   *MiniportDmaHandle = DmaBlock;
00920 
00921   return NDIS_STATUS_SUCCESS;
00922 }
00923 
00924 /*
00925  * @implemented
00926  */
00927 VOID
00928 EXPORT
00929 NdisAllocateDmaChannel(OUT PNDIS_STATUS            Status,
00930                        OUT PNDIS_HANDLE            NdisDmaHandle,
00931                        IN  NDIS_HANDLE             NdisAdapterHandle,
00932                        IN  PNDIS_DMA_DESCRIPTION   DmaDescription,
00933                        IN  ULONG                   MaximumLength)
00934 {
00935     *Status = NdisMRegisterDmaChannel(NdisDmaHandle,
00936                                       NdisAdapterHandle,
00937                                       0,
00938                                       FALSE,
00939                                       DmaDescription,
00940                                       MaximumLength);
00941 }
00942 /*
00943  * @implemented
00944  */
00945 NDIS_STATUS
00946 EXPORT
00947 NdisMRegisterInterrupt(
00948     OUT PNDIS_MINIPORT_INTERRUPT    Interrupt,
00949     IN  NDIS_HANDLE                 MiniportAdapterHandle,
00950     IN  UINT                        InterruptVector,
00951     IN  UINT                        InterruptLevel,
00952     IN  BOOLEAN                     RequestIsr,
00953     IN  BOOLEAN                     SharedInterrupt,
00954     IN  NDIS_INTERRUPT_MODE         InterruptMode)
00955 /*
00956  * FUNCTION: Claims access to an interrupt vector
00957  * ARGUMENTS:
00958  *     Interrupt             = Address of interrupt object to initialize
00959  *     MiniportAdapterHandle = Specifies handle input to MiniportInitialize
00960  *     InterruptVector       = Specifies bus-relative vector to register
00961  *     InterruptLevel        = Specifies bus-relative DIRQL vector for interrupt
00962  *     RequestIsr            = TRUE if MiniportISR should always be called
00963  *     SharedInterrupt       = TRUE if other devices may use the same interrupt
00964  *     InterruptMode         = Specifies type of interrupt
00965  * RETURNS:
00966  *     Status of operation
00967  */
00968 {
00969   NTSTATUS Status;
00970   ULONG MappedIRQ;
00971   KIRQL DIrql;
00972   KAFFINITY Affinity;
00973   PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle;
00974 
00975   NDIS_DbgPrint(MAX_TRACE, ("Called. InterruptVector (0x%X)  InterruptLevel (0x%X)  "
00976       "SharedInterrupt (%d)  InterruptMode (0x%X)\n",
00977       InterruptVector, InterruptLevel, SharedInterrupt, InterruptMode));
00978 
00979   RtlZeroMemory(Interrupt, sizeof(NDIS_MINIPORT_INTERRUPT));
00980 
00981   KeInitializeSpinLock(&Interrupt->DpcCountLock);
00982 
00983   KeInitializeDpc(&Interrupt->InterruptDpc, HandleDeferredProcessing, Adapter);
00984 
00985   KeInitializeEvent(&Interrupt->DpcsCompletedEvent, NotificationEvent, FALSE);
00986 
00987   Interrupt->SharedInterrupt = SharedInterrupt;
00988   Interrupt->IsrRequested = RequestIsr;
00989   Interrupt->Miniport = &Adapter->NdisMiniportBlock;
00990 
00991   MappedIRQ = HalGetInterruptVector(Adapter->NdisMiniportBlock.BusType, Adapter->NdisMiniportBlock.BusNumber,
00992                                     InterruptLevel, InterruptVector, &DIrql,
00993                                     &Affinity);
00994 
00995   NDIS_DbgPrint(MAX_TRACE, ("Connecting to interrupt vector (0x%X)  Affinity (0x%X).\n", MappedIRQ, Affinity));
00996 
00997   Status = IoConnectInterrupt(&Interrupt->InterruptObject, ServiceRoutine, Interrupt, &Interrupt->DpcCountLock, MappedIRQ,
00998       DIrql, DIrql, InterruptMode, SharedInterrupt, Affinity, FALSE);
00999 
01000   NDIS_DbgPrint(MAX_TRACE, ("Leaving. Status (0x%X).\n", Status));
01001 
01002   if (NT_SUCCESS(Status)) {
01003       Adapter->NdisMiniportBlock.Interrupt = Interrupt;
01004       Adapter->NdisMiniportBlock.RegisteredInterrupts++;
01005       return NDIS_STATUS_SUCCESS;
01006   }
01007 
01008   if (Status == STATUS_INSUFFICIENT_RESOURCES)
01009     {
01010         /* FIXME: Log error */
01011       NDIS_DbgPrint(MIN_TRACE, ("Resource conflict!\n"));
01012       return NDIS_STATUS_RESOURCE_CONFLICT;
01013     }
01014 
01015   NDIS_DbgPrint(MIN_TRACE, ("Function failed. Status (0x%X).\n", Status));
01016   return NDIS_STATUS_FAILURE;
01017 }
01018 
01019 
01020 /*
01021  * @implemented
01022  */
01023 NDIS_STATUS
01024 EXPORT
01025 NdisMRegisterIoPortRange(
01026     OUT PVOID       *PortOffset,
01027     IN  NDIS_HANDLE MiniportAdapterHandle,
01028     IN  UINT        InitialPort,
01029     IN  UINT        NumberOfPorts)
01030 /*
01031  * FUNCTION: Sets up driver access to device I/O ports
01032  * ARGUMENTS:
01033  *     PortOffset            = Address of buffer to place mapped base port address
01034  *     MiniportAdapterHandle = Specifies handle input to MiniportInitialize
01035  *     InitialPort           = Bus-relative base port address of a range to be mapped
01036  *     NumberOfPorts         = Specifies number of ports to be mapped
01037  * RETURNS:
01038  *     Status of operation
01039  */
01040 {
01041   PHYSICAL_ADDRESS     PortAddress, TranslatedAddress;
01042   PLOGICAL_ADAPTER Adapter  = (PLOGICAL_ADAPTER)MiniportAdapterHandle;
01043   ULONG                AddressSpace = 1;    /* FIXME The HAL handles this wrong atm */
01044 
01045   *PortOffset = 0;
01046 
01047   NDIS_DbgPrint(MAX_TRACE, ("Called - InitialPort 0x%x, NumberOfPorts 0x%x\n", InitialPort, NumberOfPorts));
01048 
01049   memset(&PortAddress, 0, sizeof(PortAddress));
01050 
01051   /*
01052    * FIXME: NDIS 5+ completely ignores the InitialPort parameter, but
01053    * we don't have a way to get the I/O base address yet (see
01054    * NDIS_MINIPORT_BLOCK->AllocatedResources and
01055    * NDIS_MINIPORT_BLOCK->AllocatedResourcesTranslated).
01056    */
01057   if(InitialPort)
01058       PortAddress = RtlConvertUlongToLargeInteger(InitialPort);
01059   else
01060       ASSERT(FALSE);
01061 
01062   NDIS_DbgPrint(MAX_TRACE, ("Translating address 0x%x 0x%x\n", PortAddress.u.HighPart, PortAddress.u.LowPart));
01063 
01064   if(!HalTranslateBusAddress(Adapter->NdisMiniportBlock.BusType, Adapter->NdisMiniportBlock.BusNumber,
01065                              PortAddress, &AddressSpace, &TranslatedAddress))
01066     {
01067       NDIS_DbgPrint(MIN_TRACE, ("Unable to translate address\n"));
01068       return NDIS_STATUS_RESOURCES;
01069     }
01070 
01071   NDIS_DbgPrint(MAX_TRACE, ("Hal returned AddressSpace=0x%x TranslatedAddress=0x%x 0x%x\n",
01072                             AddressSpace, TranslatedAddress.u.HighPart, TranslatedAddress.u.LowPart));
01073 
01074   if(AddressSpace)
01075     {
01076       ASSERT(TranslatedAddress.u.HighPart == 0);
01077       *PortOffset = (PVOID)(ULONG_PTR)TranslatedAddress.QuadPart;
01078       NDIS_DbgPrint(MAX_TRACE, ("Returning 0x%x\n", *PortOffset));
01079       return NDIS_STATUS_SUCCESS;
01080     }
01081 
01082   NDIS_DbgPrint(MAX_TRACE, ("calling MmMapIoSpace\n"));
01083 
01084   *PortOffset = MmMapIoSpace(TranslatedAddress, NumberOfPorts, MmNonCached);
01085   NDIS_DbgPrint(MAX_TRACE, ("Returning 0x%x for port range\n", *PortOffset));
01086 
01087   if(!*PortOffset) {
01088     NDIS_DbgPrint(MIN_TRACE, ("MmMapIoSpace failed\n"));
01089     return NDIS_STATUS_RESOURCES;
01090   }
01091 
01092   return NDIS_STATUS_SUCCESS;
01093 }
01094 
01095 /*
01096  * @implemented
01097  */
01098 VOID
01099 EXPORT
01100 NdisMDeregisterIoPortRange(IN  NDIS_HANDLE MiniportAdapterHandle,
01101                            IN  UINT        InitialPort,
01102                            IN  UINT        NumberOfPorts,
01103                            IN  PVOID       PortOffset)
01104 /*
01105  * FUNCTION: Releases a register mapping to I/O ports
01106  * ARGUMENTS:
01107  *     MiniportAdapterHandle = Specifies handle input to MiniportInitialize
01108  *     InitialPort           = Bus-relative base port address of a range to be mapped
01109  *     NumberOfPorts         = Specifies number of ports to be mapped
01110  *     PortOffset            = Pointer to mapped base port address
01111  */
01112 {
01113     PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle;
01114     PHYSICAL_ADDRESS PortAddress = RtlConvertUlongToLargeInteger(InitialPort);
01115     PHYSICAL_ADDRESS TranslatedAddress;
01116     ULONG AddressSpace = 1;
01117 
01118     NDIS_DbgPrint(MAX_TRACE, ("Called - InitialPort 0x%x, NumberOfPorts 0x%x, Port Offset 0x%x\n", InitialPort, NumberOfPorts, PortOffset));
01119 
01120     /* Translate the initial port again to find the address space of the translated address */
01121     if(!HalTranslateBusAddress(Adapter->NdisMiniportBlock.BusType, Adapter->NdisMiniportBlock.BusNumber,
01122                                PortAddress, &AddressSpace, &TranslatedAddress))
01123     {
01124         NDIS_DbgPrint(MIN_TRACE, ("Unable to translate address\n"));
01125         return;
01126     }
01127 
01128     /* Make sure we got the same translation as last time */
01129     ASSERT(TranslatedAddress.QuadPart == (ULONG_PTR)PortOffset);
01130 
01131     /* Check if we're in memory space */
01132     if (!AddressSpace)
01133     {
01134         NDIS_DbgPrint(MAX_TRACE, ("Calling MmUnmapIoSpace\n"));
01135 
01136         /* Unmap the memory */
01137         MmUnmapIoSpace(PortOffset, NumberOfPorts);
01138     }
01139 }
01140 
01141 /*
01142  * @implemented
01143  */
01144 VOID
01145 EXPORT
01146 NdisMUnmapIoSpace(
01147     IN  NDIS_HANDLE MiniportAdapterHandle,
01148     IN  PVOID       VirtualAddress,
01149     IN  UINT        Length)
01150 /*
01151  * FUNCTION: Un-maps space previously mapped with NdisMMapIoSpace
01152  * ARGUMENTS:
01153  *     MiniportAdapterHandle: handle originally passed into MiniportInitialize
01154  *     VirtualAddress: Address to un-map
01155  *     Length: length of the mapped memory space
01156  * NOTES:
01157  *     - Must be called at IRQL = PASSIVE_LEVEL
01158  *     - Must only be called from MiniportInitialize and MiniportHalt
01159  *     - See also: NdisMMapIoSpace
01160  * BUGS:
01161  *     - Depends on MmUnmapIoSpace to Do The Right Thing in all cases
01162  */
01163 {
01164   PAGED_CODE();
01165 
01166   ASSERT(MiniportAdapterHandle);
01167 
01168   MmUnmapIoSpace(VirtualAddress, Length);
01169 }
01170 
01171 /*
01172  * @implemented
01173  */
01174 NDIS_STATUS
01175 EXPORT
01176 NdisMInitializeScatterGatherDma(
01177     IN  NDIS_HANDLE MiniportAdapterHandle,
01178     IN  BOOLEAN     Dma64BitAddresses,
01179     IN  ULONG       MaximumPhysicalMapping)
01180 /*
01181  * FUNCTION:
01182  * ARGUMENTS:
01183  * NOTES:
01184  *    NDIS 5.0
01185  */
01186 {
01187     PLOGICAL_ADAPTER Adapter = (PLOGICAL_ADAPTER)MiniportAdapterHandle;
01188     ULONG MapRegisters;
01189     DEVICE_DESCRIPTION DeviceDesc;
01190 
01191     NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
01192 
01193     if (!(Adapter->NdisMiniportBlock.Flags & NDIS_ATTRIBUTE_BUS_MASTER)) {
01194         NDIS_DbgPrint(MIN_TRACE, ("Not a bus master\n"));
01195         return NDIS_STATUS_NOT_SUPPORTED;
01196     }
01197 
01198     RtlZeroMemory(&DeviceDesc, sizeof(DEVICE_DESCRIPTION));
01199 
01200     DeviceDesc.Version = DEVICE_DESCRIPTION_VERSION;
01201     DeviceDesc.Master = TRUE;
01202     DeviceDesc.ScatterGather = TRUE;
01203     DeviceDesc.Dma32BitAddresses = !Dma64BitAddresses;
01204     DeviceDesc.Dma64BitAddresses = Dma64BitAddresses;
01205     DeviceDesc.BusNumber = Adapter->NdisMiniportBlock.BusNumber;
01206     DeviceDesc.InterfaceType = Adapter->NdisMiniportBlock.BusType;
01207     DeviceDesc.MaximumLength = MaximumPhysicalMapping;
01208 
01209     Adapter->NdisMiniportBlock.SystemAdapterObject = 
01210          IoGetDmaAdapter(Adapter->NdisMiniportBlock.PhysicalDeviceObject, &DeviceDesc, &MapRegisters);
01211 
01212     if (!Adapter->NdisMiniportBlock.SystemAdapterObject)
01213         return NDIS_STATUS_RESOURCES;
01214 
01215     /* FIXME: Right now we just use this as a place holder */
01216     Adapter->NdisMiniportBlock.ScatterGatherListSize = 1;
01217 
01218     return NDIS_STATUS_SUCCESS;
01219 }
01220 
01221 
01222 /*
01223  * @implemented
01224  */
01225 VOID
01226 EXPORT
01227 NdisMapIoSpace(
01228     OUT PNDIS_STATUS            Status,
01229     OUT PVOID                   *VirtualAddress,
01230     IN  NDIS_HANDLE             NdisAdapterHandle,
01231     IN  NDIS_PHYSICAL_ADDRESS   PhysicalAddress,
01232     IN  UINT                    Length)
01233 /*
01234  * FUNCTION:
01235  * ARGUMENTS:
01236  * NOTES:
01237  *    NDIS 4.0
01238  */
01239 {
01240     *Status = NdisMMapIoSpace(VirtualAddress,
01241                               NdisAdapterHandle,
01242                               PhysicalAddress,
01243                               Length);
01244 }
01245 
01246 
01247 /*
01248  * @implemented
01249  */
01250 VOID
01251 EXPORT
01252 NdisFreeDmaChannel(
01253     IN  PNDIS_HANDLE    NdisDmaHandle)
01254 /*
01255  * FUNCTION:
01256  * ARGUMENTS:
01257  * NOTES:
01258  *    NDIS 4.0
01259  */
01260 {
01261     NdisMDeregisterDmaChannel(NdisDmaHandle);
01262 }
01263 
01264 
01265 
01266 /* EOF */
01267 

Generated on Sun May 27 2012 04:27:44 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.