eth8xxc.c

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

C
1,543
字号
                                 IN PVOID       InformationBuffer,
                                 IN ULONG       InformationBufferLength,
                                 OUT PULONG     BytesRead,
                                 OUT PULONG     BytesNeeded)

/*++

Description:

    ETH8XXSetInformation handles a set operation for a single OID.

    For OID_GEN_CURRENT_PACKET_FILTER, the following list of packet
    type filters are currently supported:

    NDIS_PACKET_TYPE_DIRECTED      - specific individual address
    NDIS_PACKET_MULTICAST          - list of group/individual addresses
    NDIS_PACKET_TYPE_ALL_MULTICAST - all group addresses
    NDIS_PACKET_TYPE_BROADCAST     - broadcast address FF-FF-FF-FF-FF-FF
    NDIS_PACKET_TYPE_PROMISCUOUS   - receive all regardless of address

Arguments:

    MiniportAdapterContext  - the context value that the miniport
                  returned from eth8xxInitialize
                  (actually a pointer to an ETH8XX_ADAPTER)
    Oid                     - the OID to be set
    InformationBuffer       - holds the data to be set
    InformationBufferLength - the length of InformationBuffer
    BytesRead               - if the call is successful, returns the
                      number of bytes read from InformationBuffer
    BytesNeeded             - if InformationBuffer does not contain
                      enough data to satisfy the OID, returns the
                  amount of data expected

Return Value:

    NDIS_STATUS_SUCCESS        - if the OID was successfully set
    NDIS_STATUS_PENDING        - operation will be completed asynchronously
    NDIS_STATUS_INVALID_LENGTH - incorrect information buffer length
    NDIS_STATUS_INVALID_OID    - invalid/unsupported OID

--*/
{
    /* Pointer to the adapter structure. */
    PETH8XX_ADAPTER Adapter    =
    PETH8XX_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext);
    UINT            BytesLeft  = InformationBufferLength;
    PUCHAR          InfoBuffer = (PUCHAR)(InformationBuffer);
    UINT            OidLength;
    NDIS_STATUS     Rc         = NDIS_STATUS_SUCCESS;
    ULONG           Filter;  /* Temporary holding place. */
    ULONG           LookAhead; 

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

    /* Get OID and Length of the request. */
    OidLength = BytesLeft;
    switch (Oid)
    {
        case OID_802_3_MULTICAST_LIST:
        DEBUGMSG(ZONE_INIT | ZONE_FUNCTION,
        (TEXT(" ETH8XX: OID_802_3_MULTICAST_LIST\r\n")));

        /* Verify the length. */
        if ((OidLength % ETH_LENGTH_OF_ADDRESS) != 0)
        {
            Rc = NDIS_STATUS_INVALID_LENGTH;
        *BytesRead = 0;
        *BytesNeeded = 0;
        break;
        }

        /* Set the new list on the adapter. */
        NdisMoveMemory(Adapter->Addresses, InfoBuffer, OidLength);

        /* If we are currently receiving all multicast or
         * we are promsicuous then we DO NOT call this, or
             * it will reset those settings.
         */
        if (!(Adapter->PacketFilter & (NDIS_PACKET_TYPE_ALL_MULTICAST
                     | NDIS_PACKET_TYPE_PROMISCUOUS)))
        {
        Adapter->NbrMulticasts = OidLength / ETH_LENGTH_OF_ADDRESS;
            Rc = eth8xxSetMulticastAddressList(Adapter);

        } else {

            /* List of multicast addresses kept in Adapter->Addresses. */
            Rc = NDIS_STATUS_SUCCESS;
        }
        break;
        case OID_GEN_CURRENT_PACKET_FILTER:
        DEBUGMSG(ZONE_INIT | ZONE_FUNCTION,
        (TEXT(" ETH8XX: OID_GEN_CURRENT_PACKET_FILTER\r\n")));

        if (OidLength != 4 )
        {
            Rc = NDIS_STATUS_INVALID_LENGTH;
        *BytesRead = 0;
        *BytesNeeded = 0;

        } else {

        NdisMoveMemory(&Filter, InfoBuffer, 4);

        DEBUGMSG(ZONE_INIT,
            (TEXT(" ETH8XX: Previous Filter: %d\r\n"),
            Adapter->PrevFilter));
        DEBUGMSG(ZONE_INIT,
            (TEXT(" ETH8XX: Current Filter : %d\r\n"),
            Adapter->PacketFilter));
        DEBUGMSG(ZONE_INIT,
            (TEXT(" ETH8XX: New Filter     : %d\r\n"), Filter));

        /* Verify that the requested filter is supported. */
        if (Filter & ~(NDIS_PACKET_TYPE_DIRECTED
                 | NDIS_PACKET_TYPE_MULTICAST
                 | NDIS_PACKET_TYPE_ALL_MULTICAST
                 | NDIS_PACKET_TYPE_PROMISCUOUS
                 | NDIS_PACKET_TYPE_BROADCAST
                 ))
        {
            DEBUGMSG(ZONE_ERROR,
            (TEXT(" ETH8XX: returning NDIS_STATUS_NOT_SUPPORTED\r\n")));

            Rc = NDIS_STATUS_NOT_SUPPORTED;
            *BytesRead   = 4;
            *BytesNeeded = 0;

        } else {

            /* Set the new value on the adapter. */
            Adapter->PrevFilter   = Adapter->PacketFilter;
            Adapter->PacketFilter = Filter;
            Rc = eth8xxSetPacketFilter(Adapter);
        }
        }
        break;
        case OID_GEN_CURRENT_LOOKAHEAD:
        DEBUGMSG(ZONE_INIT | ZONE_FUNCTION,
        (TEXT(" ETH8XX: OID_CUR_LOOKAHEAD\r\n")));

        /* Verify the length. */
        if (OidLength != 4)
        {
        Rc = NDIS_STATUS_INVALID_LENGTH;
        *BytesRead = 0;
        *BytesNeeded = 0;
        break;
        }

        /* Store the new value. */
        NdisMoveMemory(&LookAhead, InfoBuffer, 4);
        if (LookAhead <= (ULONG)ETH8XX_MAX_LOOKAHEAD)
        {
            Adapter->MaxLookAhead = LookAhead;

        } else {

            Rc = NDIS_STATUS_INVALID_LENGTH;
        }
        break;
        default:
        DEBUGMSG(ZONE_INIT | ZONE_FUNCTION,
        (TEXT(" ETH8XX: OID_INVALID\r\n")));
        *BytesRead = 0;
        *BytesNeeded = 0;
        Rc = NDIS_STATUS_INVALID_OID;
    }

    if (Rc == NDIS_STATUS_SUCCESS)
    {
        *BytesRead = BytesLeft;
    *BytesNeeded = 0;
    }

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

    return(Rc);
}


/*----------------------------------------------------------------------*/
NDIS_STATUS eth8xxSetPacketFilter(IN PETH8XX_ADAPTER Adapter)
/*++

Description:

    Configures the incoming frame address filter for the Ethernet
    interface. The "if...else" blocks are there to avoid unnecessary
    hardware accesses which in some cases can be time consuming
    (specifically if the Ethernet interface has to be stopped and
    then restarted).

Arguments:

    Adapter - pointer to the NDIS miniport adapter block

Return Value:

    NDIS_STATUS_SUCCESS - successfully updated address filter
    NDIS_STATUS_FAILURE - failed to update address filter

Notes:

    Note that to receive all multicast packets the multicast
    registers on the Ethernet interface must be filled with 1's.
    To be promiscuous that must be done as well as setting the
    promiscuous physical flag in the PSMR. This must be done
    as long as ANY protocol bound to this adapter has their
    filter set accordingly.

--*/
{
    NDIS_STATUS rc = NDIS_STATUS_SUCCESS;

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

    /* Handle setting/clearing ALL MULTICAST mode filter. */
    if (Adapter->PacketFilter & NDIS_PACKET_TYPE_ALL_MULTICAST)
    {
    if (!(Adapter->PrevFilter & NDIS_PACKET_TYPE_ALL_MULTICAST))
    {
        /* Enable reception of "all multicast" frames. */
        rc = HW_Set_All_Multicast(Adapter, TRUE);
    }

    } else if ((Adapter->PacketFilter & NDIS_PACKET_TYPE_MULTICAST)
    &&         (Adapter->NbrMulticasts > 0)) {

    /* No need for ALL MULTICAST, use specific multicast addresses. */
    rc = eth8xxSetMulticastAddressList(Adapter);

    } else if (Adapter->PrevFilter & NDIS_PACKET_TYPE_ALL_MULTICAST) {

    /* Turn off "all multicast" mode. */
    rc = HW_Set_All_Multicast(Adapter, FALSE);
    }

    /* Handle setting/clearing PROMISCUOUS mode filter. */
    if (Adapter->PacketFilter & NDIS_PACKET_TYPE_PROMISCUOUS)
    {
    if (!(Adapter->PrevFilter & NDIS_PACKET_TYPE_PROMISCUOUS))
    {
        /* Enable reception of all frames. */
        HW_Set_Promiscuous(Adapter, TRUE);
    }

    } else if (Adapter->PrevFilter & NDIS_PACKET_TYPE_PROMISCUOUS) {

    /* Disable promiscuous mode. */
    HW_Set_Promiscuous(Adapter, FALSE);
    }

    /* Handle setting/clearing BROADCAST reception mode filter. */
    if (Adapter->PacketFilter & NDIS_PACKET_TYPE_BROADCAST)
    {
        if (!(Adapter->PrevFilter & NDIS_PACKET_TYPE_BROADCAST))
    {
        /* Turn on receiving all broadcast frames. */
        HW_Set_Broadcast(Adapter, TRUE);
    }

    } else if (Adapter->PrevFilter & NDIS_PACKET_TYPE_BROADCAST) {

    /* Discard all broadcast frames. */
    HW_Set_Broadcast(Adapter, FALSE);
    }

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

    return(NDIS_STATUS_SUCCESS);
}


/*----------------------------------------------------------------------*/
NDIS_STATUS eth8xxSetMulticastAddressList(IN PETH8XX_ADAPTER Adapter)
/*++

Description:

    Sets the Ethernet multicast address list for this adapter.

Arguments:

    Adapter - pointer to the NDIS miniport adapter block

Return Value:

    NDIS_STATUS_SUCCESS - successfully set multicast list
    NDIS_STATUS_FAILURE - failed to update multicast list

Notes:

    When invoked, we must ensure that the multicast list in the filter
    package becomes the multicast list for the adapter. To do this, we
    determine the required contents of the CPM multicast registers and
    update them. The MPC821 User's Guide also states that the adapter
    does not need to be stopped prior to executing the SET GROUP ADDRESS
    command.

--*/
{
    NDIS_STATUS rc = NDIS_STATUS_FAILURE;

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

    /* Update the Individual and Group multicast registers. */
    if (HW_Fill_Multicast_Regs(Adapter))
    {
    rc = NDIS_STATUS_SUCCESS;
    }

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

    return(rc);
}


/*----------------------------------------------------------------------*/
NDIS_STATUS eth8xxSend(IN NDIS_HANDLE MiniportAdapterContext,
                       IN PNDIS_PACKET Packet,
                       IN UINT Flags)
/*++

Description:

    The eth8xxSend request instructs the driver to transmit a packet
    through the Ethernet interface onto the medium.

Arguments:

    MiniportAdapterContext - Context registered with the wrapper, really
                             a pointer to the adapter.
    Packet                 - A pointer to a descriptor for the packet that
                             is to be transmitted.
    SendFlags              - Optional send flags.

Notes:

    This miniport driver will accept multiple send requests (until
    the transmit queue is filled up). This will keep the CPM as busy
    as possible, i.e. when a transmit interrupt has been handled the
    next transmission can be immediately initiated.

--*/
{
    PETH8XX_ADAPTER Adapter =
    PETH8XX_ADAPTER_FROM_CONTEXT_HANDLE(MiniportAdapterContext);
    NDIS_STATUS sendStatus;

    DEBUGMSG(ZONE_FUNCTION | ZONE_XMIT,
    (TEXT("+ETH8XX: eth8xxSend\r\n")));

    EnterCriticalSection(&v_UpdateTxBufList);

    /* Put the packet on the send queue. */
    if (Adapter->FirstPacket == NULL)
    {
    Adapter->FirstPacket = Packet;

    } else {

    RESERVED(Adapter->LastPacket)->Next = Packet;
    }
    RESERVED(Packet)->Next = NULL;
    Adapter->LastPacket = Packet;

    LeaveCriticalSection(&v_UpdateTxBufList);

    /* Process the send queue. */
    sendStatus = eth8xxDoNextSend(Adapter, FALSE);

    DEBUGMSG(ZONE_FUNCTION | ZONE_XMIT,
    (TEXT("-ETH8XX: eth8xxSend\r\n")));

    return(sendStatus);
}

⌨️ 快捷键说明

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