Esempio n. 1
0
NDIS_STATUS NICInitializeAdapter(
    IN  PMP_ADAPTER  Adapter,
    IN  NDIS_HANDLE  WrapperConfigurationContext
    )
/*++
Routine Description:

    Query assigned resources and initialize the adapter.

Arguments:

    Adapter     Pointer to our adapter

Return Value:

    NDIS_STATUS_SUCCESS
    NDIS_STATUS_ADAPTER_NOT_FOUND  

--*/    
{

    
    NDIS_STATUS         Status = NDIS_STATUS_ADAPTER_NOT_FOUND;      
    typedef __declspec(align(MEMORY_ALLOCATION_ALIGNMENT)) NicResourceCharBuf;            
    NicResourceCharBuf  resBuf[NIC_RESOURCE_BUF_SIZE];
    PNDIS_RESOURCE_LIST resList = (PNDIS_RESOURCE_LIST)resBuf;
    UINT                bufSize = NIC_RESOURCE_BUF_SIZE;
    PCM_PARTIAL_RESOURCE_DESCRIPTOR pResDesc;
    ULONG               index;

    DEBUGP(MP_TRACE, ("---> InitializeAdapter\n"));
    PAGED_CODE();

    do
    {
        //     
        // Get the resources assigned by the PNP manager. NDIS gets
        // these resources in IRP_MN_START_DEVICE request.
        //
        NdisMQueryAdapterResources(
            &Status, 
            WrapperConfigurationContext, 
            resList, 
            &bufSize);
    
        if (Status == NDIS_STATUS_SUCCESS)
        {
#pragma prefast(suppress: 8199, "resList is initialized by NdisMQueryAdapterResources")                           
            for (index=0; index < resList->Count; index++)
            {
                pResDesc = &resList->PartialDescriptors[index];

                switch(pResDesc->Type)
                {
                    case CmResourceTypePort:
                        DEBUGP(MP_INFO, ("IoBaseAddress = 0x%x\n", 
                            NdisGetPhysicalAddressLow(pResDesc->u.Port.Start)));
                        DEBUGP(MP_INFO, ("IoRange = x%x\n", 
                                    pResDesc->u.Port.Length));
                        break;

                    case CmResourceTypeInterrupt:                   
                        DEBUGP(MP_INFO, ("InterruptLevel = x%x\n", 
                                            pResDesc->u.Interrupt.Level));
                        break;

                    case CmResourceTypeMemory:
                        DEBUGP(MP_INFO, ("MemPhysAddress(Low) = 0x%0x\n", 
                           NdisGetPhysicalAddressLow(pResDesc->u.Memory.Start)));
                        DEBUGP(MP_INFO, ("MemPhysAddress(High) = 0x%0x\n", 
                            NdisGetPhysicalAddressHigh(pResDesc->u.Memory.Start)));
                        break;
                }
            } 
        }
        
        Status = NDIS_STATUS_SUCCESS;

        //
        // Map bus-relative IO range to system IO space using 
        // NdisMRegisterIoPortRange
        //

        //        
        // Map bus-relative registers to virtual system-space
        // using NdisMMapIoSpace
        //
        

        //
        // Disable interrupts here as soon as possible
        //
                     
        //
        // Register the interrupt using NdisMRegisterInterrupt
        //
        
        //
        // Initialize the hardware with mapped resources
        //
        
#ifdef NDIS50_MINIPORT
        //
        // Register a shutdown handler for NDIS50 or earlier miniports
        // For NDIS51 miniports, set AdapterShutdownHandler.
        //
        NdisMRegisterAdapterShutdownHandler(
            Adapter->AdapterHandle,
            (PVOID) Adapter,
            (ADAPTER_SHUTDOWN_HANDLER) MPShutdown);
#endif         

        //
        // Enable the interrupt
        //
        
    } while (FALSE);
     
    DEBUGP(MP_TRACE, ("<--- InitializeAdapter, Status=%x\n", Status));

    return Status;

}
Esempio n. 2
0
/*+
 *
 * AllocateAdapterMemory
 *
 * Routine Description:
 *
 *     This routine allocates memory for:
 *
 *     - Transmit descriptor ring
 *     - Receive descriptor ring
 *     - Receive buffers
 *     - Transmit buffer
 *     - Setup buffer
 *
 * Arguments:
 *
 *     Adapter - The adapter to allocate memory for.
 *
 * Functional description
 *
 *     For each allocated zone, we maintain a set of pointers:
 *        - virtual & physical addresses of the allocated block
 *        - virtual & physical addresses of the aligned structure (descriptor ring, buffer,...)
 *          whithin  the block
 *
 * Return Value:
 *
 *     Returns FALSE if an allocation fails.
 *
-*/
extern
BOOLEAN
AllocateAdapterMemory(
        IN PDC21X4_ADAPTER Adapter
        )
{
   PDC21X4_TRANSMIT_DESCRIPTOR TransmitDescriptor;
   PDC21X4_RECEIVE_DESCRIPTOR ReceiveDescriptor;

   NDIS_STATUS Status;

   PRCV_HEADER RcvHeader;
   PNDIS_PACKET Packet;

   ULONG AllocSize;
   PULONG AllocVa;
   NDIS_PHYSICAL_ADDRESS AllocPa;
   ULONG Va;

   ULONG Pa;

   UINT i;
   ULONG Offset;

   INT TransmitDescriptorRingSize;
   INT ReceiveDescriptorRingSize;

   Adapter->RcvHeaderSize =
           ((RCV_HEADER_SIZE + Adapter->CacheLineSize - 1) / Adapter->CacheLineSize)
         * Adapter->CacheLineSize;


#if _DBG
   DbgPrint("Alloc Rcv_ring[%d desc.], Txm_ring[%d desc.], setup_buf[%d]...\n",
      Adapter->ReceiveRingSize,
      TRANSMIT_RING_SIZE,
      DC21X4_SETUP_BUFFER_SIZE
      );
#endif

   // Allocate space for transmit descriptor ring,
   // the receive descriptor ring and the setup buffer

   TransmitDescriptorRingSize =
      Adapter->DescriptorSize * TRANSMIT_RING_SIZE;
   ReceiveDescriptorRingSize =
      Adapter->DescriptorSize * Adapter->ReceiveRingSize;

   Adapter->DescriptorRing.AllocSize =
      TransmitDescriptorRingSize
      + ReceiveDescriptorRingSize
      + DC21X4_SETUP_BUFFER_SIZE
      + Adapter->CacheLineSize;

   NdisMAllocateSharedMemory(
      Adapter->MiniportAdapterHandle,
      Adapter->DescriptorRing.AllocSize,
      FALSE,                                           // NON-CACHED
      (PVOID *)&Adapter->DescriptorRing.AllocVa,       // virtual ...
      &Adapter->DescriptorRing.AllocPa                 // and physical address of the allocation
      );

   // Check the allocation success

   if ((PVOID)Adapter->DescriptorRing.AllocVa == (PVOID)NULL) {
      return FALSE;
   }
   if (NdisGetPhysicalAddressHigh(Adapter->DescriptorRing.AllocPa) != 0) {
      return FALSE;
   }

   NdisZeroMemory (
      (PVOID)(Adapter->DescriptorRing.AllocVa),
      (ULONG)(Adapter->DescriptorRing.AllocSize)
      );

   // Align to the next cache line boundary

   AlignStructure (
      &Adapter->DescriptorRing,
      Adapter->CacheLineSize
      );

   Adapter->TransmitDescriptorRingVa = Adapter->DescriptorRing.Va;
   Adapter->TransmitDescriptorRingPa = Adapter->DescriptorRing.Pa;
   Offset = TransmitDescriptorRingSize;

   Adapter->ReceiveDescriptorRingVa =  Adapter->DescriptorRing.Va + Offset;
   Adapter->ReceiveDescriptorRingPa =  Adapter->DescriptorRing.Pa + Offset;
   Offset += ReceiveDescriptorRingSize;

   Adapter->SetupBufferVa = Adapter->DescriptorRing.Va + Offset;
   Adapter->SetupBufferPa = Adapter->DescriptorRing.Pa + Offset;

   //Initialize the setup buffer

   NdisZeroMemory (
      (PVOID)(Adapter->SetupBufferVa),
      DC21X4_SETUP_BUFFER_SIZE
      );


   // Allocate a pool of NDIS buffers

   NdisAllocateBufferPool(
        &Status,
        &Adapter->FlushBufferPoolHandle,
        ( Adapter->ReceiveRingSize
        + Adapter->ExtraReceiveBuffers
        + DC21X4_NUMBER_OF_MAX_TRANSMIT_BUFFERS
        + DC21X4_NUMBER_OF_MIN_TRANSMIT_BUFFERS )
        );

   if (Status != NDIS_STATUS_SUCCESS) {
      return FALSE;
   }


   //  Allocate a pool of packets.
#if _DBG
   DbgPrint("Allocate PacketPool [%d packets]\n",
      Adapter->ExtraReceivePackets);
#endif
   NdisAllocatePacketPool(
      &Status,
      &Adapter->ReceivePacketPool,
      Adapter->ExtraReceivePackets,
      0
      );

   if (Status != NDIS_STATUS_SUCCESS) {
      return FALSE;
   }

   // Allocate all of the packets out of the packet pool
   // and place them on a queue.

   for (i = 0; i < Adapter->ExtraReceivePackets; i++) {

      // Allocate a packet from the pool.
      NdisAllocatePacket(
         &Status,
         &Packet,
         Adapter->ReceivePacketPool
         );
      if (Status != NDIS_STATUS_SUCCESS) {
         return(FALSE);
      }

      // Set the header size in the packet's Out-Of-Band information.
      // All other fields in the Out-Of-Band information have been
      // initialized to 0 by NdisAllocatePacket().

      NDIS_SET_PACKET_HEADER_SIZE(Packet, ETH_HEADER_SIZE);

      // Place it on the receive packet free list.

      RCV_RESERVED(Packet)->Next = Adapter->FreePacketList;
      Adapter->FreePacketList = Packet;
   }

   //  Clear out the free receive list of buffers.
   Adapter->FreeRcvList = NULL;


   //  We allocate the receive buffers.  We allocate both
   //  the buffers for the descriptor ring and the extra
   //  buffers and place them all on the free queue.

#if _DBG
   DbgPrint("Allocate Receive Buffers [%d]\n",
      Adapter->ExtraReceiveBuffers+Adapter->ReceiveRingSize);
#endif

   // Attempt to allocate all the receive buffer space
   // in one block
   // If it fails,allocate each buffer individually

   //  Allocation size
   Adapter->RcvBufferSpace.AllocSize =
      ((Adapter->ExtraReceiveBuffers + Adapter->ReceiveRingSize)
      * (DC21X4_RECEIVE_BUFFER_SIZE + Adapter->RcvHeaderSize))
      + Adapter->CacheLineSize;


   NdisMAllocateSharedMemory(
      Adapter->MiniportAdapterHandle,
      Adapter->RcvBufferSpace.AllocSize,
      TRUE,
      (PVOID *)&Adapter->RcvBufferSpace.AllocVa,
      &Adapter->RcvBufferSpace.AllocPa
      );

   // Check the allocation success
   if (((PVOID)Adapter->RcvBufferSpace.AllocVa != (PVOID)NULL)
      && (NdisGetPhysicalAddressHigh(Adapter->RcvBufferSpace.AllocPa) == 0)) {

        NdisZeroMemory (
          (PVOID)(Adapter->RcvBufferSpace.AllocVa),
          (ULONG)(Adapter->RcvBufferSpace.AllocSize)
          );

       // Align to the next cache line boundary

       AlignStructure (
          &Adapter->RcvBufferSpace,
          Adapter->CacheLineSize
          );

       //  Allocation size needed for the receive buffer
       AllocSize = DC21X4_RECEIVE_BUFFER_SIZE
                 + Adapter->RcvHeaderSize;
       Offset=0;
   }
   else
   {
       //  Allocation size needed for the receive buffer
       AllocSize = DC21X4_RECEIVE_BUFFER_SIZE
                 + Adapter->RcvHeaderSize
                 + Adapter->CacheLineSize;


       Adapter->RcvBufferSpace.Va=0;
   }

   for (i = 0;
      i < (Adapter->ExtraReceiveBuffers + Adapter->ReceiveRingSize);
      i++
      ) {

      if (Adapter->RcvBufferSpace.Va != 0) {

          Va = Adapter->RcvBufferSpace.Va + Offset;
          Pa = Adapter->RcvBufferSpace.Pa + Offset;
          Offset += AllocSize;

      }
      else
      {
          //  Allocate a receive buffer.

          NdisMAllocateSharedMemory(
             Adapter->MiniportAdapterHandle,
             AllocSize,
             TRUE,
             (PVOID *)&AllocVa,
             &AllocPa
             );
          if (((PVOID)AllocVa == (PVOID)NULL)
             || (NdisGetPhysicalAddressHigh(AllocPa) != 0)) {
             return FALSE;
          }

          NdisZeroMemory(AllocVa, AllocSize);

          //  Align on the cache line boundary

          Offset = Adapter->CacheLineSize - ((ULONG)AllocVa % Adapter->CacheLineSize);
          Va = (ULONG)(AllocVa) + Offset;
          Pa = NdisGetPhysicalAddressLow(AllocPa) + Offset;

      }

      //The receive header points to the aligned va.

      RcvHeader = (PRCV_HEADER)Va;

      RcvHeader->AllocVa = (ULONG)AllocVa;
      RcvHeader->AllocPa = AllocPa;
      RcvHeader->AllocSize = (USHORT)AllocSize;

      // These addresses point to the data buffer

      RcvHeader->Va = (ULONG)(Va + Adapter->RcvHeaderSize);
      RcvHeader->Pa = Pa + Adapter->RcvHeaderSize;
      RcvHeader->Size = DC21X4_RECEIVE_BUFFER_SIZE;

#if DBG
      RcvHeader->Signature = 'dHxR';
#if _DBG
      DbgPrint(
         "%-3d RcvHeader: %lx, RcvBuffer: %lx/%lx, HeaderSize: %lx\n",
         i,RcvHeader,
         RcvHeader->Va,
         RcvHeader->Pa,
         Adapter->RcvHeaderSize
         );
#endif
#endif
      //  Allocate an NDIS flush buffer for each receive buffer.

      NdisAllocateBuffer(
         &Status,
         &RcvHeader->FlushBuffer,
         Adapter->FlushBufferPoolHandle,
         (PVOID)RcvHeader->Va,
         DC21X4_RECEIVE_BUFFER_SIZE
         );
      if (Status != NDIS_STATUS_SUCCESS) {
         return FALSE;
      }

      // Grab a packet off of the free packet list and
      // associate it with the buffer.

      Packet = Adapter->FreePacketList;
      Adapter->FreePacketList = RCV_RESERVED(Packet)->Next;

      // Chain the buffer on the packet.

      NdisChainBufferAtFront(Packet, RcvHeader->FlushBuffer);

      // Save a pointer to the receive header with the packet.

      RCV_RESERVED(Packet)->RcvHeader = RcvHeader;

      // Save the packet with the receive header.

      RcvHeader->Packet = Packet;

      // Place the descriptor on the free queue.

      RcvHeader->Next = Adapter->FreeRcvList;
      Adapter->FreeRcvList = RcvHeader;

      Adapter->CurrentReceiveBufferCount++;
   }


#if _DBG
   DbgPrint("Init Rcv ring..\n");
#endif

   //  Assign the receive buffers to the descriptors.

   for (i = 0,
      ReceiveDescriptor = (PDC21X4_RECEIVE_DESCRIPTOR)Adapter->ReceiveDescriptorRingVa,
      Pa = Adapter->ReceiveDescriptorRingPa;
      i < Adapter->ReceiveRingSize;
      i++,
      (PCHAR)ReceiveDescriptor += Adapter->DescriptorSize,
      Pa += Adapter->DescriptorSize
      ) {

      // Grab a receive buffer from the free list.

      ASSERT(Adapter->FreeRcvList != NULL);
      RcvHeader = Adapter->FreeRcvList;
      Adapter->FreeRcvList = RcvHeader->Next;

      Adapter->CurrentReceiveBufferCount--;

      // Associate the buffer with the descriptor.

      ReceiveDescriptor->RcvHeader = RcvHeader;
      ReceiveDescriptor->FirstBufferAddress = RcvHeader->Pa;


      ReceiveDescriptor->Status = DESC_OWNED_BY_DC21X4;
      ReceiveDescriptor->Control = DC21X4_RECEIVE_BUFFER_SIZE;

      ReceiveDescriptor->Next =
         (PDC21X4_RECEIVE_DESCRIPTOR)((PCHAR)ReceiveDescriptor + Adapter->DescriptorSize);

   }

   //last descriptor of the ring

   (PCHAR)ReceiveDescriptor -= Adapter->DescriptorSize;
   ReceiveDescriptor->Control |= DC21X4_RDES_SECOND_ADDR_CHAINED;
   ReceiveDescriptor->SecondBufferAddress = Adapter->ReceiveDescriptorRingPa;
   ReceiveDescriptor->Next =
      (PDC21X4_RECEIVE_DESCRIPTOR)Adapter->ReceiveDescriptorRingVa;

#if _DBG
   DbgPrint("Init Txm ring..\n");
#endif

   // Initialize the Transmit Descriptor ring

   for (i=0,
      TransmitDescriptor = (PDC21X4_TRANSMIT_DESCRIPTOR)Adapter->TransmitDescriptorRingVa,
      Pa = Adapter->TransmitDescriptorRingPa;
      i < TRANSMIT_RING_SIZE;
      i++,
      (PCHAR)TransmitDescriptor += Adapter->DescriptorSize,
      Pa += Adapter->DescriptorSize
      ) {

      TransmitDescriptor->MapTableIndex = i * NUMBER_OF_SEGMENT_PER_DESC;
      TransmitDescriptor->DescriptorPa = Pa;
      TransmitDescriptor->Next =
         (PDC21X4_TRANSMIT_DESCRIPTOR)((PCHAR)TransmitDescriptor + Adapter->DescriptorSize);

   }

   //last descriptor of the ring
   (PCHAR)TransmitDescriptor -= Adapter->DescriptorSize;
   TransmitDescriptor->Control = DC21X4_TDES_SECOND_ADDR_CHAINED;
   TransmitDescriptor->SecondBufferAddress = Adapter->TransmitDescriptorRingPa;
   TransmitDescriptor->Next =
      (PDC21X4_TRANSMIT_DESCRIPTOR)Adapter->TransmitDescriptorRingVa;


   // Txm buffers

   for (i = 0;i < DC21X4_NUMBER_OF_MAX_TRANSMIT_BUFFERS;i ++) {

      Adapter->MaxTransmitBuffer[i].AllocSize =
         DC21X4_MAX_TRANSMIT_BUFFER_SIZE + Adapter->CacheLineSize;

      NdisMAllocateSharedMemory(
         Adapter->MiniportAdapterHandle,
         Adapter->MaxTransmitBuffer[i].AllocSize,
         TRUE,                                           // CACHED
         (PVOID *)&Adapter->MaxTransmitBuffer[i].AllocVa,   // virtual ...
         &Adapter->MaxTransmitBuffer[i].AllocPa             // and physical address of the buffer allocation
         );

      // Check the allocation success

      if (((PVOID)Adapter->MaxTransmitBuffer[i].AllocVa == (PVOID)NULL)
         || (NdisGetPhysicalAddressHigh(Adapter->MaxTransmitBuffer[i].AllocPa) != 0)) {
         return FALSE;
      }

      // Align the buffer on the cache line boundary

      AlignStructure (
         &Adapter->MaxTransmitBuffer[i],
         Adapter->CacheLineSize
         );


      // Allocate an NDIS flush buffer for each transmit buffer

      NdisAllocateBuffer(
         &Status,
         &Adapter->MaxTransmitBuffer[i].FlushBuffer,
         Adapter->FlushBufferPoolHandle,
         (PVOID)Adapter->MaxTransmitBuffer[i].Va,
         DC21X4_MAX_TRANSMIT_BUFFER_SIZE
         );

      if (Status != NDIS_STATUS_SUCCESS) {
         return FALSE;
      }
   }

   // Allocate the minimal packet buffers

   Adapter->MinTransmitBuffer[0].AllocSize =
       (DC21X4_NUMBER_OF_MIN_TRANSMIT_BUFFERS * DC21X4_MIN_TRANSMIT_BUFFER_SIZE)
     + Adapter->CacheLineSize;

   NdisMAllocateSharedMemory(
     Adapter->MiniportAdapterHandle,
     Adapter->MinTransmitBuffer[0].AllocSize,
     TRUE,                                              // CACHED
     (PVOID *)&Adapter->MinTransmitBuffer[0].AllocVa,   // virtual ...
     &Adapter->MinTransmitBuffer[0].AllocPa             // and physical address of the buffer allocation
     );

   // Check the allocation success

   if (((PVOID)Adapter->MinTransmitBuffer[0].AllocVa == (PVOID)NULL)
       || (NdisGetPhysicalAddressHigh(Adapter->MinTransmitBuffer[0].AllocPa) != 0)) {

	  Adapter->DontUseMinTransmitBuffer = TRUE;
      return TRUE;
   }

   // Align the buffer on the cache line boundary

   AlignStructure (
      &Adapter->MinTransmitBuffer[0],
      Adapter->CacheLineSize
      );

   for (i = 0;i < DC21X4_NUMBER_OF_MIN_TRANSMIT_BUFFERS;i ++) {

      Offset = i * DC21X4_MIN_TRANSMIT_BUFFER_SIZE;

      Adapter->MinTransmitBuffer[i].Va =
          Adapter->MinTransmitBuffer[0].Va + Offset;

      Adapter->MinTransmitBuffer[i].Pa =
          Adapter->MinTransmitBuffer[0].Pa + Offset;

      // Allocate an NDIS flush buffer for each transmit buffer

      NdisAllocateBuffer(
         &Status,
         &Adapter->MinTransmitBuffer[i].FlushBuffer,
         Adapter->FlushBufferPoolHandle,
         (PVOID)Adapter->MinTransmitBuffer[i].Va,
         DC21X4_MIN_TRANSMIT_BUFFER_SIZE
         );

      if (Status != NDIS_STATUS_SUCCESS) {
         return FALSE;
      }
   }

   // Allocation has completed successfully

   return TRUE;
}