eth8xxc.c

来自「WinCE 3.0 BSP, 包含Inter SA1110, Intel_815」· C语言 代码 · 共 1,543 行 · 第 1/4 页

C
1,543
字号
    eth8xxMiniportBlock.NdisWrapperHandle = NULL;

        InitStatus = STATUS_UNSUCCESSFUL;

    } else {

    /* Now ready to call the Adapter initialization function. */
    DEBUGMSG(ZONE_INIT,
        (TEXT("*ETH8XX: NdisMRegisterMiniport SUCCEEDED\r\n")));

    InitStatus = STATUS_SUCCESS;
    }

    DEBUGMSG(ZONE_INIT | ZONE_FUNCTION,
    (TEXT("-ETH8XX: DriverEntry\r\n")));

    return(InitStatus);
}


/*----------------------------------------------------------------------*/
#pragma NDIS_PAGEABLE_FUNCTION(eth8xxInitialize)

NDIS_STATUS eth8xxInitialize(OUT PNDIS_STATUS OpenErrorStatus,
                             OUT PUINT        SelectedMediumIndex,
                             IN  PNDIS_MEDIUM MediumArray,
                             IN  UINT         MediumArraySize,
                             IN  NDIS_HANDLE  MiniportAdapterHandle,
                             IN  NDIS_HANDLE  ConfigurationHandle)
/*++

Description:

    Eth8xxInitialize starts the Ethernet controller and registers
    resources with the wrapper. This function is a required miniport
    function.

    The configuration and operation of this driver can be changed via
    values set in the registry under the ETH8XX1 key. Currently the
    following options are available:

    "NetworkAddress"=hex:xx,xx,xx,xx,xx,xx
    "Heartbeat"=dword:x
    "MaxMulticastList"=dword:x

    To override the default Ethernet address currently hardcoded into
    the HW_Read_Eth_Address() routine in hw.c, just provide a six byte
    value for "NetworkAddress". If no value is given, then the default
    hardcoded address will be used. Note that this can result in network
    conflicts and unreliable operation. The "Heartbeat" value should be
    set to 1 to enable the use of a heartbeat signal to automatically
    test the built-in collision detection circuitry. If this value is
    0 or not specified at all, then heartbeat checking is disabled.
    Enabling the heartbeat hardware will not impact performance in any
    way since the signal is generated during the normal inter-frame gap
    period. The "MaxMulticastList" value is used to specify the maximum
    size of the multicast address list (i.e., the maximum number of
    Ethernet multicast addresses that can be stored by the driver).

Arguments:

    OpenErrorStatus       - Additional error status information.
    SelectedMediumIndex   - Index of the media type supported by the driver.
    MediumArray           - Array of media types for the driver to chose from.
    MediumArraySize       - Number of entries in the array.
    MiniportAdapterHandle - Handle for passing to the wrapper when
                            referring to this adapter.
    ConfigurationHandle   - A handle to pass to NdisOpenConfiguration.

Return Value:

    NDIS_STATUS_SUCCESS       - if adapter successfully initialized
    NDIS_STATUS_UNSUPPORTED_MEDIA - if 802.3 is not supported
    NDIS_STATUS_FAILURE       - if adapter initialization failed

--*/
{
    PETH8XX_ADAPTER Adapter;          /* Pointer to the adapter block.  */
    NDIS_HANDLE     ConfigHandle;     /* Registry handle.               */
    BOOLEAN         ConfigError;      /* Return code.                   */
    ULONG           ConfigErrorValue; /* Value of error.                */
    PVOID           NetAddress = NULL;/* Ethernet address to use.       */
    UINT            Length     = 0;   /* Length of Ethernet adddress.   */
    UINT            MaxMulticastList; /* Number of multicast addresses. */
    ULONG           i;                /* Simple loop counter.           */
    NDIS_STATUS     Status;           /* NDIS return code.              */
    PNDIS_CONFIGURATION_PARAMETER ReturnedValue; /* Registry data.      */

    /* String names of all the parameters that will be read.            */
    NDIS_STRING HeartbeatStr        = NDIS_STRING_CONST("Heartbeat");
    NDIS_STRING MaxMulticastListStr = NDIS_STRING_CONST("MaxMulticastList");

    DEBUGMSG(ZONE_INIT | ZONE_FUNCTION,
    (TEXT("+ETH8XX: eth8xxInitialize\r\n")));

    /* Initialize misc. local variables. */
    ConfigError      = FALSE;
    ConfigErrorValue = 0;

    /* Search for the medium type (802.3) in the given array. */
    for (i = 0; i < MediumArraySize; i++)
    {
        if (MediumArray[i] == NdisMedium802_3)
    {
        /* Return the selected medium index to NDIS. */
        *SelectedMediumIndex = i;
            break;
        }
    }

    if (i == MediumArraySize)
    {
        DEBUGMSG(ZONE_INIT | ZONE_ERROR,
        (TEXT("*ETH8XX: FAILED - Unsupported media\r\n")));

        return(NDIS_STATUS_UNSUPPORTED_MEDIA);
    }

    /* Allocate memory for the adapter block now. */
    Status = NdisAllocateMemory((PVOID *)&Adapter,
                sizeof(ETH8XX_ADAPTER),
                0,
                HighestAcceptableMax
                   );
    if (Status != NDIS_STATUS_SUCCESS)
    {
        DEBUGMSG(ZONE_INIT | ZONE_ERROR,
            (TEXT("*ETH8XX: NdisAllocateMemory FAILED (0x%X)\r\n"),
        Status));
        return(Status);
    }

    /* Clear out the adapter block. */
    NdisZeroMemory (Adapter, sizeof(ETH8XX_ADAPTER));

    /* Open the configuration space, i.e. get a handle to the
     * [HKEY_LOCAL_MACHINE\Comm\ETH8XX1\Parms] registry key.
     */
    NdisOpenConfiguration(&Status, &ConfigHandle, ConfigurationHandle);

    /* Check if HEARTBEAT checking is to be used. */
    NdisReadConfiguration(&Status,
              &ReturnedValue,
              ConfigHandle,
              &HeartbeatStr,
              NdisParameterInteger);
    if ((Status == NDIS_STATUS_SUCCESS)
    &&  ((UINT)ReturnedValue->ParameterData.IntegerData > 0))
    {
    /* Enable use of heartbeat circuitry. */
    Adapter->UseHeartbeat =  TRUE;

    } else {

    /* Do not use heartbeat circuitry. */
    Adapter->UseHeartbeat =  FALSE;
    }

    /* Read the Ethernet address to be used. */
    NdisReadNetworkAddress(&Status, &NetAddress, &Length, ConfigHandle);
    if ((Status == NDIS_STATUS_SUCCESS)
    &&  (Length == ETH_LENGTH_OF_ADDRESS))
    {
        /* Save the address that should be used. */
        NdisMoveMemory(Adapter->StationAddr,
               NetAddress,
               ETH_LENGTH_OF_ADDRESS);
    }

    /* Read (optional) MaxMulticastList from registry. */
    NdisReadConfiguration(&Status,
              &ReturnedValue,
              ConfigHandle,
              &MaxMulticastListStr,
              NdisParameterInteger);
    if ((Status == NDIS_STATUS_SUCCESS)
    &&  (ReturnedValue->ParameterData.IntegerData <= DEFAULT_MULTICASTLISTMAX))
    {
    /* Use value from registry. */
    MaxMulticastList = ReturnedValue->ParameterData.IntegerData;

    } else {

    /* Use default value. */
    MaxMulticastList = DEFAULT_MULTICASTLISTMAX;
    }

    /* Close the configuration space. */
    NdisCloseConfiguration(ConfigHandle);

    /* Now use this information to register with the NDIS wrapper
     * and to initialize the adapter.
     */
    Adapter->Status                = DISABLED;
    Adapter->NbrRxBuffers          = DEFAULT_NBR_RX_BUFFERS;
    Adapter->NbrTxBuffers          = DEFAULT_NBR_TX_BUFFERS;
    Adapter->MaxRxBufferSize       = ETH_BUFFER_SIZE;
    Adapter->MaxTxBufferSize       = ETH_BUFFER_SIZE;
    Adapter->MulticastListMax      = MaxMulticastList;
    Adapter->MiniportAdapterHandle = MiniportAdapterHandle;
    Adapter->MaxLookAhead          = ETH8XX_MAX_LOOKAHEAD;

    DEBUGMSG(ZONE_INIT,
    (TEXT(" ETH8XX: Registering adapter with %d Rx + %d Tx buffers")
         TEXT(" (total %ld bytes)\r\n"),
    Adapter->NbrRxBuffers,
    Adapter->NbrTxBuffers,
    Adapter->NbrRxBuffers * Adapter->MaxRxBufferSize +
        Adapter->NbrTxBuffers * Adapter->MaxTxBufferSize));

    /* Now register the adapter. */
    if (eth8xxRegisterAdapter(Adapter, ConfigurationHandle,
          ConfigError, ConfigErrorValue) != NDIS_STATUS_SUCCESS)
    {
        /* eth8xxRegisterAdapter failed. */
        NdisFreeMemory(Adapter, sizeof(ETH8XX_ADAPTER), 0);

        DEBUGMSG(ZONE_INIT | ZONE_ERROR,
        (TEXT("*ETH8XX: eth8xxRegisterAdapter FAILED\r\n")));

        Status = NDIS_STATUS_FAILURE;

    } else {

    DEBUGMSG(ZONE_INIT, (TEXT("*ETH8XX: Successful\r\n")));

    Status = NDIS_STATUS_SUCCESS;
    }

    DEBUGMSG(ZONE_INIT | ZONE_FUNCTION,
    (TEXT("-ETH8XX: eth8xxInitialize\r\n")));

    return(Status);
}


/*----------------------------------------------------------------------*/
#pragma NDIS_PAGEABLE_FUNCTION(eth8xxRegisterAdapter)

NDIS_STATUS eth8xxRegisterAdapter(IN PETH8XX_ADAPTER Adapter,
                                  IN NDIS_HANDLE ConfigurationHandle,
                                  IN BOOLEAN ConfigError,
                                  IN ULONG ConfigErrorValue)
/*++

Description:

    Called when a new adapter should be registered. It allocates
    space for the adapter, initializes the adapter's block,
    registers resources with the wrapper and initializes the
    physical adapter. If this call completes successfully, then
    the Ethernet interface is fully configured and ready for use.

    The final step to enabling the Ethernet interface is to call
    HW_Toggle_Eth_If(). However, the MC68160 Ethernet transceiver
    appears to be in an unknown state after power-up. Hence, we
    must first enable the interface, pause for a short period of
    time, then disable, and finally reenable it. By doing this, we
    can ensure that the initial ARP broadcast packet sent by NDIS
    is properly transmitted. If we just enable the interface once,
    then we don't seem to get the first ARP packet but everything
    else works just fine.

    Note that the delay value supplied to NdisStallExecution() must
    not exceed 50 microseconds since all interrupt handling and
    thread activity is suspended for the duration of the delay.

Arguments:

    Adapter             - pointer to the NDIS miniport adapter block
    ConfigurationHandle - handle passed to eth8xxInitialize()
    ConfigError         - configuration read error flag
    ConfigErrorValue    - value to log if there is an error

Return Value:

    NDIS_STATUS_SUCCESS           - if adapter successfully registered
    NDIS_STATUS_FAILURE           - if adapter registration failed
    NDIS_STATUS_ADAPTER_NOT_FOUND - if hardware setup failed

--*/
{
    PETH8XX_ADAPTER TmpAdapter;
    NDIS_STATUS     status;  /* NDIS call return code. */

    DEBUGMSG(ZONE_INIT | ZONE_FUNCTION,
    (TEXT("+ETH8XX: eth8xxRegisterAdapter\r\n")));

    /* Check for a configuration error. */
    if (ConfigError)
    {
        /* Log the error and exit. */
        DEBUGMSG(ZONE_INIT | ZONE_ERROR,
            (TEXT("*ETH8XX: ConfigError is set to %d\r\n"),
            ConfigErrorValue));

        NdisWriteErrorLogEntry(Adapter->MiniportAdapterHandle,
            NDIS_ERROR_CODE_UNSUPPORTED_CONFIGURATION,1,ConfigErrorValue);

        return(NDIS_STATUS_FAILURE);
    }

    /* Inform the wrapper of the physical attributes of this adapter.   
     * Not a bus-master (FALSE) and a host-specific internal I/F (0).
     */
    NdisMSetAttributes(Adapter->MiniportAdapterHandle,
               (NDIS_HANDLE)Adapter,
                       FALSE,
               NdisInterfaceInternal);

    /* Initialize the CPM. */
    if (!HW_Initialize(Adapter))
    {
        /* The CPM seems to have failed, not likely. */
        DEBUGMSG(ZONE_INIT | ZONE_ERROR,
            (TEXT("*ETH8XX: HW_Initialize() failed\r\n")));

        NdisWriteErrorLogEntry(Adapter->MiniportAdapterHandle,
                               NDIS_ERROR_CODE_ADAPTER_NOT_FOUND,
                   0);
        status = NDIS_STATUS_ADAPTER_NOT_FOUND;

        goto fail2;
    }

    /* Read the Ethernet address off of the PROM. */
    if (!HW_Read_Eth_Address(Adapter))
    {
        DEBUGMSG(ZONE_INIT | ZONE_ERROR,
            (TEXT("*ETH8XX: could not read the Ethernet address\r\n")));

        NdisWriteErrorLogEntry(Adapter->MiniportAdapterHandle,
                   NDIS_ERROR_CODE_ADAPTER_NOT_FOUND,
                   0);
        status = NDIS_STATUS_ADAPTER_NOT_FOUND;

        goto fail2;
    }

    /* Link us on to the chain of adapters for this driver. */
    Adapter->NextAdapter = eth8xxMiniportBlock.AdapterQueue;
    eth8xxMiniportBlock.AdapterQueue = Adapter;

    InitializeCriticalSection(&v_UpdateTxBufList);

    /* Setup the Ethernet interface using the initialization information. */
    if (!HW_Setup(Adapter))
    {
        /* The CPM could not be written to. */
        NdisWriteErrorLogEntry(Adapter->MiniportAdapterHandle,
                   NDIS_ERROR_CODE_ADAPTER_NOT_FOUND,
                   0);
        status = NDIS_STATUS_ADAPTER_NOT_FOUND;

        goto fail3;
    }

    /* Initialize the interrupt. */
    status = NdisMRegisterInterrupt(&Adapter->Interrupt,
                    Adapter->MiniportAdapterHandle,
                    ADS_NETWORK_INTERRUPT_VEC,
                    ADS_NETWORK_INTERRUPT_LVL,
                    FALSE,
                    FALSE,
                    NdisInterruptLatched); 
    if (status != NDIS_STATUS_SUCCESS)
    {
        DEBUGMSG(ZONE_INIT|ZONE_ERROR,
            (TEXT("*ETH8XX:NdisMRegisterInterrupt FAILED\r\n")));

        NdisWriteErrorLogEntry(Adapter->MiniportAdapterHandle,
                   NDIS_ERROR_CODE_INTERRUPT_CONNECT,
                   0);

        goto fail3;
    }

    /* OK now to enable the Ethernet interface (see note above). */
    HW_Toggle_Eth_If(Adapter, TRUE);
    NdisStallExecution(40);
    HW_Toggle_Eth_If(Adapter, FALSE);
    HW_Toggle_Eth_If(Adapter, TRUE);

    DEBUGMSG(ZONE_INIT, (TEXT(" ETH8XX: interrupt connected\r\n")));

    /* Register a shutdown handler for the Ethernet interface. */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?