Changeset 320bd52 in mainline for uspace/drv/nic/rtl8169/driver.c


Ignore:
Timestamp:
2014-08-18T19:33:40Z (10 years ago)
Author:
Agnieszka Tabaka <nufcia@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
c62a8275
Parents:
aa2f865
Message:

Add proper receive filtering for broadcast, multicast and unicast frames.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/nic/rtl8169/driver.c

    raa2f865 r320bd52  
    738738        /* Configure Receive Control Register */
    739739        uint32_t rcr = pio_read_32(rtl8169->regs + RCR);
     740        rtl8169->rcr_ucast = RCR_ACCEPT_PHYS_MATCH;
    740741        rcr |= RCR_ACCEPT_PHYS_MATCH | RCR_ACCEPT_ERROR | RCR_ACCEPT_RUNT;
    741742        pio_write_32(rtl8169->regs + RCR, rcr);
     
    793794}
    794795
     796/** Notify NIC framework about HW filtering state when promisc mode was disabled
     797 *
     798 *  @param nic_data     The NIC data
     799 *  @param mcast_mode   Current multicast mode
     800 *  @param was_promisc  Sign if the promiscuous mode was active before disabling
     801 */
     802inline static void rtl8169_rcx_promics_rem(nic_t *nic_data,
     803    nic_multicast_mode_t mcast_mode, uint8_t was_promisc)
     804{
     805        assert(nic_data);
     806
     807        if (was_promisc != 0) {
     808                if (mcast_mode == NIC_MULTICAST_LIST)
     809                        nic_report_hw_filtering(nic_data, 1, 0, -1);
     810                else
     811                        nic_report_hw_filtering(nic_data, 1, 1, -1);
     812        } else {
     813                nic_report_hw_filtering(nic_data, 1, -1, -1);
     814        }
     815}
     816
    795817static int rtl8169_unicast_set(nic_t *nic_data, nic_unicast_mode_t mode,
    796818    const nic_address_t *addr, size_t addr_count)
    797819{
     820        rtl8169_t *rtl8169 = nic_get_specific(nic_data);
     821        uint32_t rcr = pio_read_32(rtl8169->regs + RCR);
     822        uint8_t was_promisc = rcr & RCR_ACCEPT_ALL_PHYS;
     823        nic_multicast_mode_t mcast_mode;
     824
     825        nic_query_multicast(nic_data, &mcast_mode, 0, NULL, NULL);
     826
     827        ddf_msg(LVL_DEBUG, "Unicast RX filter mode: %d", mode);
     828
     829
     830        switch (mode) {
     831        case NIC_UNICAST_BLOCKED:
     832                rtl8169->rcr_ucast = 0;
     833                rtl8169_rcx_promics_rem(nic_data, mcast_mode, was_promisc);
     834                break;
     835        case NIC_UNICAST_DEFAULT:
     836                rtl8169->rcr_ucast = RCR_ACCEPT_PHYS_MATCH;
     837                rtl8169_rcx_promics_rem(nic_data, mcast_mode, was_promisc);
     838                break;
     839        case NIC_UNICAST_LIST:
     840                rtl8169->rcr_ucast = RCR_ACCEPT_PHYS_MATCH | RCR_ACCEPT_ALL_PHYS;
     841
     842                if (mcast_mode == NIC_MULTICAST_PROMISC)
     843                        nic_report_hw_filtering(nic_data, 0, 1, -1);
     844                else
     845                        nic_report_hw_filtering(nic_data, 0, 0, -1);
     846                break;
     847        case NIC_UNICAST_PROMISC:
     848                rtl8169->rcr_ucast = RCR_ACCEPT_PHYS_MATCH | RCR_ACCEPT_ALL_PHYS;
     849
     850                if (mcast_mode == NIC_MULTICAST_PROMISC)
     851                        nic_report_hw_filtering(nic_data, 1, 1, -1);
     852                else
     853                        nic_report_hw_filtering(nic_data, 1, 0, -1);
     854                break;
     855        default:
     856                return ENOTSUP;
     857        }
     858
     859        fibril_mutex_lock(&rtl8169->rx_lock);
     860
     861        rcr &= ~(RCR_ACCEPT_PHYS_MATCH | RCR_ACCEPT_ALL_PHYS);
     862        pio_write_32(rtl8169->regs + RCR, rcr | rtl8169->rcr_ucast | rtl8169->rcr_mcast);
     863        ddf_msg(LVL_DEBUG, "new RCR value: 0x%08x", rcr | rtl8169->rcr_ucast | rtl8169->rcr_mcast);
     864
     865        fibril_mutex_unlock(&rtl8169->rx_lock);
    798866        return EOK;
    799867}
     
    802870    const nic_address_t *addr, size_t addr_count)
    803871{
     872        rtl8169_t *rtl8169 = nic_get_specific(nic_data);
     873        uint32_t rcr = pio_read_32(rtl8169->regs + RCR);
     874        uint64_t mask;
     875
     876        ddf_msg(LVL_DEBUG, "Multicast RX filter mode: %d", mode);
     877
     878        switch (mode) {
     879        case NIC_MULTICAST_BLOCKED:
     880                rtl8169->rcr_mcast = 0;
     881                if ((rtl8169->rcr_ucast & RCR_ACCEPT_ALL_PHYS) != 0)
     882                        nic_report_hw_filtering(nic_data, -1, 0, -1);
     883                else
     884                        nic_report_hw_filtering(nic_data, -1, 1, -1);
     885                break;
     886        case NIC_MULTICAST_LIST:
     887                mask = nic_mcast_hash(addr, addr_count);
     888                pio_write_32(rtl8169->regs + MAR0, (uint32_t)mask);
     889                pio_write_32(rtl8169->regs + MAR0 + 4, (uint32_t)(mask >> 32));
     890                rtl8169->rcr_mcast = RCR_ACCEPT_MULTICAST;
     891                nic_report_hw_filtering(nic_data, -1, 0, -1);
     892                break;
     893        case NIC_MULTICAST_PROMISC:
     894                pio_write_32(rtl8169->regs + MAR0, 0xffffffffULL);
     895                pio_write_32(rtl8169->regs + MAR0 + 4, (uint32_t)(0xffffffffULL >> 32));
     896                rtl8169->rcr_mcast = RCR_ACCEPT_MULTICAST;
     897                nic_report_hw_filtering(nic_data, -1, 1, -1);
     898                break;
     899        default:
     900                return ENOTSUP;
     901        }
     902
     903        fibril_mutex_lock(&rtl8169->rx_lock);
     904
     905        rcr &= ~(RCR_ACCEPT_PHYS_MATCH | RCR_ACCEPT_ALL_PHYS);
     906        pio_write_32(rtl8169->regs + RCR, rcr | rtl8169->rcr_ucast | rtl8169->rcr_mcast);
     907        ddf_msg(LVL_DEBUG, "new RCR value: 0x%08x", rcr | rtl8169->rcr_ucast | rtl8169->rcr_mcast);
     908
     909        fibril_mutex_unlock(&rtl8169->rx_lock);
    804910        return EOK;
    805911}
     
    811917        /* Configure Receive Control Register */
    812918        uint32_t rcr = pio_read_32(rtl8169->regs + RCR);
    813         rcr |= RCR_ACCEPT_BROADCAST;           
     919
     920        ddf_msg(LVL_DEBUG, "Broadcast RX filter mode: %d", mode);
     921
     922        switch (mode) {
     923        case NIC_BROADCAST_BLOCKED:
     924                rcr &= RCR_ACCEPT_BROADCAST;
     925                break;
     926        case NIC_BROADCAST_ACCEPTED:
     927                rcr |= RCR_ACCEPT_BROADCAST;
     928                break;
     929        default:
     930                return ENOTSUP;
     931        }
     932
    814933        pio_write_32(rtl8169->regs + RCR, rcr);
     934        ddf_msg(LVL_DEBUG," new RCR value: 0x%08x", rcr);
     935
    815936        return EOK;
    816937}
Note: See TracChangeset for help on using the changeset viewer.