Пример #1
0
/*
 * AlignStructure
 *
 * Align a structure within a bloc of allocated memory
 * on a specified boundary
 *
 */
VOID
AlignStructure (
        IN PALLOCATION_MAP Map,
        IN UINT Boundary
        )
{
   ULONG AlignmentOffset;

   AlignmentOffset = Boundary - ((ULONG)(Map->AllocVa) % Boundary);
   Map->Va = (ULONG)(Map->AllocVa) + AlignmentOffset;
   Map->Pa = NdisGetPhysicalAddressLow(Map->AllocPa)+ AlignmentOffset;

}
Пример #2
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;

}
Пример #3
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;
}
Пример #4
0
VOID
NE3200ResetHandler(
    IN PVOID SystemSpecific1,
    IN PNE3200_ADAPTER Adapter,
    IN PVOID SystemSpecific2,
    IN PVOID SystemSpecific3
    )

/*++

Routine Description:

    This manages the reset/download process.  It is
    responsible for resetting the adapter, waiting for proper
    status, downloading MAC.BIN, waiting for MAC.BIN initialization,
    and optionally sending indications to the appropriate protocol.

    Since the NE3200's status registers must be polled during the
    reset/download process, this is implemented as a state machine.

Arguments:

    Adapter - The adapter whose hardware is to be initialized.

Return Value:

    None.

--*/
{

    //
    // Physical address of the MAC.BIN buffer.
    //
    NDIS_PHYSICAL_ADDRESS MacBinPhysicalAddress;

    //
    // Status from the adapter.
    //
    UCHAR Status;

    //
    // Simple iteration counter.
    //
    UINT i;

    //
    // Loop until the reset has completed.
    //
    while (Adapter->ResetState != NE3200ResetStateComplete) {

        switch (Adapter->ResetState) {

            //
            // The first stage of resetting an NE3200
            //
            case NE3200ResetStateStarting :

                //
                // Unfortunately, a hardware reset to the NE3200 does *not*
                // reset the BMIC chip.  To ensure that we read a proper status,
                // we'll clear all of the BMIC's registers.
                //
                NE3200_WRITE_SYSTEM_INTERRUPT(
                    Adapter,
                    0
                    );

                //
                // I changed this to ff since the original 0 didn't work for
                // some cases. since we don't have the specs....
                //
                NE3200_WRITE_LOCAL_DOORBELL_INTERRUPT(
                    Adapter,
                    0xff
                    );

                NE3200_WRITE_SYSTEM_DOORBELL_MASK(
                    Adapter,
                    0
                    );

                NE3200_SYNC_CLEAR_SYSTEM_DOORBELL_INTERRUPT(
                    Adapter
                    );

                for (i = 0 ; i < 16 ; i += 4 ) {

                    NE3200_WRITE_MAILBOX_ULONG(
                        Adapter,
                        i,
                        0L
                        );

                }

                //
                // Toggle the NE3200's reset line.
                //
                NE3200_WRITE_RESET(
                    Adapter,
                    NE3200_RESET_BIT_ON
                    );

                NE3200_WRITE_RESET(
                    Adapter,
                    NE3200_RESET_BIT_OFF
                    );

                //
                // Switch to the next state.
                //
                Adapter->ResetState = NE3200ResetStateResetting;
                Adapter->ResetTimeoutCounter = NE3200_TIMEOUT_RESET;

                //
                // Loop to the next processing
                //
                break;

            //
            // Part Deux.  The actual downloading of the software.
            //
            case NE3200ResetStateResetting :

                //
                // Read the status mailbox.
                //
                NE3200_READ_MAILBOX_UCHAR(Adapter, NE3200_MAILBOX_RESET_STATUS, &Status);

                if (Status == NE3200_RESET_PASSED) {

                    //
                    // We have good reset.  Initiate the MAC.BIN download.
                    //

                    //
                    // The station address for this adapter can be forced to
                    // a specific value at initialization time.  When MAC.BIN
                    // first gets control, it reads mailbox 10.  If this mailbox
                    // contains a 0xFF, then the burned-in PROM station address
                    // is used.  If this mailbox contains any value other than
                    // 0xFF, then mailboxes 10-15 are read.  The six bytes
                    // stored in these mailboxes then become the station address.
                    //
                    // Since we have no need for this feature, we will always
                    // initialize mailbox 10 with a 0xFF.
                    //
                    NE3200_WRITE_MAILBOX_UCHAR(
                        Adapter,
                        NE3200_MAILBOX_STATION_ID,
                        0xFF
                        );


                    //
                    // Get the MAC.BIN buffer.
                    //
                    MacBinPhysicalAddress = NE3200Globals.MacBinPhysicalAddress;

                    //
                    // Download MAC.BIN to the card.
                    //
                    NE3200_WRITE_MAILBOX_USHORT(
                        Adapter,
                        NE3200_MAILBOX_MACBIN_LENGTH,
                        NE3200Globals.MacBinLength
                        );

                    NE3200_WRITE_MAILBOX_UCHAR(
                        Adapter,
                        NE3200_MAILBOX_MACBIN_DOWNLOAD_MODE,
                        NE3200_MACBIN_DIRECT
                        );

                    NE3200_WRITE_MAILBOX_ULONG(
                        Adapter,
                        NE3200_MAILBOX_MACBIN_POINTER,
                        NdisGetPhysicalAddressLow(MacBinPhysicalAddress)
                        );

                    NE3200_WRITE_MAILBOX_USHORT(
                        Adapter,
                        NE3200_MAILBOX_MACBIN_TARGET,
                        NE3200_MACBIN_TARGET_ADDRESS >> 1
                        );

                    //
                    // This next OUT "kicks" the loader into action.
                    //
                    NE3200_WRITE_MAILBOX_UCHAR(
                        Adapter,
                        NE3200_MAILBOX_RESET_STATUS,
                        0
                        );

                    //
                    // Switch to the next state.
                    //
                    Adapter->ResetState = NE3200ResetStateDownloading;
                    Adapter->ResetTimeoutCounter = NE3200_TIMEOUT_DOWNLOAD;

                    //
                    // Loop to the next state.
                    //

                } else if (Status == NE3200_RESET_FAILED) {

                    //
                    // Reset failure.  Notify the authorities and
                    // next of kin.
                    //
                    Adapter->ResetResult = NE3200ResetResultResetFailure;
                    Adapter->ResetState = NE3200ResetStateComplete;

                    NE3200DoResetIndications(Adapter, NDIS_STATUS_HARD_ERRORS);

                } else {

                    //
                    // Still waiting for results, check if we have
                    // timed out waiting.
                    //
                    Adapter->ResetTimeoutCounter--;

                    if (Adapter->ResetTimeoutCounter == 0) {

                        //
                        // We've timed-out.  Bad news.  Notify the death.
                        //
                        Adapter->ResetResult = NE3200ResetResultResetTimeout;
                        Adapter->ResetState = NE3200ResetStateComplete;

                        NE3200DoResetIndications(Adapter, NDIS_STATUS_HARD_ERRORS);

                    } else {

                        //
                        // For Synchronous resets, we stall.  For async,
                        // we set a timer to check later.
                        //
                        if (!Adapter->ResetAsynchronous) {

                            //
                            // Otherwise, wait and try again.
                            //
                            NdisStallExecution(10000);

                        } else{

                            //
                            // Try again later.
                            //
                            NdisMSetTimer(&Adapter->ResetTimer, 100);

                            return;

                        }

                    }

                }

                break;

            //
            // Part Three: The download was started.  Check for completion,
            // and reload the current station address.
            //
            case NE3200ResetStateDownloading :

                //
                // Read the download status.
                //
                NE3200_READ_MAILBOX_UCHAR(Adapter, NE3200_MAILBOX_STATUS, &Status);

                if (Status == NE3200_INITIALIZATION_PASSED) {

                    //
                    // According to documentation from Compaq, this next port
                    // write will (in a future MAC.BIN) tell MAC.BIN whether or
                    // not to handle loopback internally.  This value is currently
                    // not used, but must still be written to the port.
                    //
                    NE3200_WRITE_MAILBOX_UCHAR(
                        Adapter,
                        NE3200_MAILBOX_STATUS,
                        1
                        );

                    //
                    // Initialization is good, the card is ready.
                    //
                    NE3200StartChipAndDisableInterrupts(Adapter,
                                                        Adapter->ReceiveQueueHead
                                                       );

                    {

                        //
                        // Do the work for updating the current address
                        //

                        //
                        // This points to the public Command Block.
                        //
                        PNE3200_SUPER_COMMAND_BLOCK CommandBlock;

                        //
                        // This points to the adapter's configuration block.
                        //
                        PNE3200_CONFIGURATION_BLOCK ConfigurationBlock =
                            Adapter->ConfigurationBlock;

                        //
                        // Get a public command block.
                        //
                        NE3200AcquirePublicCommandBlock(Adapter,
                                                        &CommandBlock
                                                       );

                        Adapter->ResetHandlerCommandBlock = CommandBlock;

                        //
                        // Setup the command block.
                        //

                        CommandBlock->NextCommand = NULL;

                        CommandBlock->Hardware.State = NE3200_STATE_WAIT_FOR_ADAPTER;
                        CommandBlock->Hardware.Status = 0;
                        CommandBlock->Hardware.NextPending = NE3200_NULL;
                        CommandBlock->Hardware.CommandCode =
                            NE3200_COMMAND_CONFIGURE_82586;
                        CommandBlock->Hardware.PARAMETERS.CONFIGURE.ConfigurationBlock =
                            NdisGetPhysicalAddressLow(Adapter->ConfigurationBlockPhysical);

                        //
                        // Now that we've got the command block built,
                        // let's do it!
                        //
                        NE3200SubmitCommandBlock(Adapter, CommandBlock);

                        Adapter->ResetState = NE3200ResetStateReloadAddress;
                        Adapter->ResetTimeoutCounter = NE3200_TIMEOUT_DOWNLOAD;

                    }

                } else if (Status == NE3200_INITIALIZATION_FAILED) {

                    //
                    // Initialization failed.  Notify the wrapper.
                    //
                    Adapter->ResetResult = NE3200ResetResultInitializationFailure;
                    Adapter->ResetState = NE3200ResetStateComplete;

                    NE3200DoResetIndications(Adapter, NDIS_STATUS_HARD_ERRORS);

                } else {

                    //
                    // See if we've timed-out waiting for the download to
                    // complete.
                    //
                    Adapter->ResetTimeoutCounter--;

                    if (Adapter->ResetTimeoutCounter == 0) {

                        //
                        // We've timed-out.  Bad news.
                        //
                        Adapter->ResetResult = NE3200ResetResultInitializationTimeout;
                        Adapter->ResetState = NE3200ResetStateComplete;

                        NE3200DoResetIndications(Adapter, NDIS_STATUS_HARD_ERRORS);

                    } else {

                        //
                        // For Synchronous resets, we stall.  For async,
                        // we set a timer to check later.
                        //
                        if (!Adapter->ResetAsynchronous) {

                            //
                            // Otherwise, wait and try again.
                            //
                            NdisStallExecution(10000);

                        } else{

                            //
                            // Try again later.
                            //
                            NdisMSetTimer(&Adapter->ResetTimer, 100);
                            return;

                        }

                    }

                }

                break;

            //
            // Part Last: Waiting for the configuring of the adapter
            // to complete
            //
            case NE3200ResetStateReloadAddress :

                //
                // Read the command block status.
                //
                if (Adapter->ResetHandlerCommandBlock->Hardware.State ==
                    NE3200_STATE_EXECUTION_COMPLETE) {

                    //
                    // return this command block
                    //
                    NE3200RelinquishCommandBlock(Adapter,
                                                 Adapter->ResetHandlerCommandBlock
                                                );

                    //
                    // Reset is complete.  Do those indications.
                    //
                    Adapter->ResetResult = NE3200ResetResultSuccessful;
                    Adapter->ResetState = NE3200ResetStateComplete;

                    NE3200DoResetIndications(Adapter, NDIS_STATUS_SUCCESS);

                } else {

                    //
                    // See if we've timed-out.
                    //
                    Adapter->ResetTimeoutCounter--;

                    if (Adapter->ResetTimeoutCounter == 0) {

                        //
                        // We've timed-out.  Bad news.
                        //

                        //
                        // return this command block
                        //
                        NE3200RelinquishCommandBlock(Adapter,
                                                     Adapter->ResetHandlerCommandBlock
                                                    );

                        Adapter->ResetResult = NE3200ResetResultInitializationTimeout;
                        Adapter->ResetState = NE3200ResetStateComplete;

                        NE3200DoResetIndications(Adapter, NDIS_STATUS_HARD_ERRORS);

                    } else {

                        if ( Adapter->ResetTimeoutCounter ==
                                (NE3200_TIMEOUT_DOWNLOAD/2) ) {

                            //
                            // The command may have stalled, try again.
                            //
                            NE3200_WRITE_LOCAL_DOORBELL_INTERRUPT(
                                Adapter,
                                NE3200_LOCAL_DOORBELL_NEW_COMMAND
                                );

                        }

                        //
                        // For Synchronous resets, we stall.  For async,
                        // we set a timer to check later.
                        //
                        if (!Adapter->ResetAsynchronous) {

                            //
                            // Otherwise, wait and try again.
                            //
                            NdisStallExecution(10000);

                        } else{

                            //
                            // Check again later
                            //
                            NdisMSetTimer(&Adapter->ResetTimer, 100);
                            return;

                        }

                    }

                }

                break;

            default :

                //
                // Somehow, we reached an invalid state.
                //

                //
                // We'll try to salvage our way out of this.
                //
                Adapter->ResetResult = NE3200ResetResultInvalidState;
                Adapter->ResetState = NE3200ResetStateComplete;

                NE3200DoResetIndications(Adapter, NDIS_STATUS_HARD_ERRORS);

                NdisWriteErrorLogEntry(
                    Adapter->MiniportAdapterHandle,
                    NDIS_ERROR_CODE_HARDWARE_FAILURE,
                    3,
                    resetDpc,
                    NE3200_ERRMSG_BAD_STATE,
                    (ULONG)(Adapter->ResetState)
                    );

                break;
        }
Пример #5
0
VOID
NE3200StartChipAndDisableInterrupts(
    IN PNE3200_ADAPTER Adapter,
    IN PNE3200_SUPER_RECEIVE_ENTRY FirstReceiveEntry
    )

/*++

Routine Description:

    This routine is used to start an already initialized NE3200,
    but to keep the interrupt line masked.

Arguments:

    Adapter - The adapter for the NE3200 to start.

    FirstReceiveEntry - Pointer to the first receive entry to be
    used by the adapter.

Return Value:

    None.

--*/

{

    IF_LOG('%');

    //
    // Write the new receive pointer.
    //
    NE3200_WRITE_RECEIVE_POINTER(
        Adapter,
        NdisGetPhysicalAddressLow(FirstReceiveEntry->Self)
        );

    NE3200_WRITE_LOCAL_DOORBELL_INTERRUPT(
        Adapter,
        NE3200_LOCAL_DOORBELL_NEW_RECEIVE
        );

    //
    // Initialize the doorbell & system interrupt masks
    //
    NE3200_WRITE_SYSTEM_DOORBELL_MASK(
        Adapter,
        0
        );

    NE3200_WRITE_SYSTEM_INTERRUPT(
        Adapter,
        NE3200_SYSTEM_INTERRUPT_ENABLE
        );

    NE3200_WRITE_MAILBOX_UCHAR(
        Adapter,
        NE3200_MAILBOX_STATUS,
        0
        );

}