Ignore:
File:
1 edited

Legend:

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

    r96e368a ra4666a9  
    2727 */
    2828
    29 #define _DDF_DATA_IMPLANT
    30 
    3129#include <assert.h>
    3230#include <errno.h>
    3331#include <align.h>
    3432#include <byteorder.h>
     33#include <irc.h>
    3534#include <libarch/barrier.h>
    3635
     
    7574static int rtl8169_on_stopped(nic_t *nic_data);
    7675static void rtl8169_send_frame(nic_t *nic_data, void *data, size_t size);
    77 static void rtl8169_irq_handler(ddf_dev_t *dev, ipc_callid_t iid,
    78     ipc_call_t *icall);
     76static void rtl8169_irq_handler(ipc_callid_t iid, ipc_call_t *icall,
     77    ddf_dev_t *dev);
    7978static inline int rtl8169_register_int_handler(nic_t *nic_data);
    8079static inline void rtl8169_get_hwaddr(rtl8169_t *rtl8169, nic_address_t *addr);
     
    329328}
    330329
     330static void rtl8169_dev_cleanup(ddf_dev_t *dev)
     331{
     332        assert(dev);
     333
     334        if (ddf_dev_data_get(dev))
     335                nic_unbind_and_destroy(dev);
     336}
     337
    331338static int rtl8169_dev_initialize(ddf_dev_t *dev)
    332339{
     
    350357failed:
    351358        ddf_msg(LVL_ERROR, "The device initialization failed");
    352 //      rtl8139_dev_cleanup(dev);
     359        rtl8169_dev_cleanup(dev);
    353360        return ret;
    354361
     
    388395        rtl8169_t *rtl8169 = nic_get_specific(nic_data);
    389396
     397        /* Get PCI VID & PID */
     398        rc = pci_config_space_read_16(ddf_dev_parent_sess_get(dev),
     399            PCI_VENDOR_ID, &rtl8169->pci_vid);
     400        if (rc != EOK)
     401                return rc;
     402
     403        rc = pci_config_space_read_16(ddf_dev_parent_sess_get(dev),
     404            PCI_DEVICE_ID, &rtl8169->pci_pid);
     405        if (rc != EOK)
     406                return rc;
     407
    390408        /* Map register space */
    391409        rc = pio_enable(rtl8169->regs_phys, RTL8169_IO_SIZE, &rtl8169->regs);
     
    419437        pio_write_8(rtl8169->regs + CR, cr_value | CR_TE | CR_RE);
    420438
    421         rc = nic_connect_to_services(nic_data);
    422         if (rc != EOK) {
    423                 ddf_msg(LVL_ERROR, "Failed to connect to services (%d)", rc);
    424                 goto err_irq;
    425         }
    426 
    427439        fun = ddf_fun_create(nic_get_ddf_dev(nic_data), fun_exposed, "port0");
    428440        if (fun == NULL) {
     
    433445        nic_set_ddf_fun(nic_data, fun);
    434446        ddf_fun_set_ops(fun, &rtl8169_dev_ops);
    435         ddf_fun_data_implant(fun, nic_data);
    436447
    437448        rc = ddf_fun_bind(fun);
     
    461472err_pio:
    462473err_destroy:
    463         //rtl8169_dev_cleanup(dev);
     474        rtl8169_dev_cleanup(dev);
    464475        return rc;
    465476
     
    473484        int rc;
    474485
    475         rtl8169_set_hwaddr(rtl8169, addr);
     486        fibril_mutex_lock(&rtl8169->rx_lock);
     487        fibril_mutex_lock(&rtl8169->tx_lock);
    476488
    477489        rc = nic_report_address(nic_data, addr);
     
    479491                return rc;
    480492
     493        rtl8169_set_hwaddr(rtl8169, addr);
     494
     495        fibril_mutex_unlock(&rtl8169->rx_lock);
     496        fibril_mutex_unlock(&rtl8169->tx_lock);
     497
    481498        return EOK;
    482499}
     
    484501static int rtl8169_get_device_info(ddf_fun_t *fun, nic_device_info_t *info)
    485502{
    486 
    487         str_cpy(info->vendor_name, NIC_VENDOR_MAX_LENGTH, "Realtek");
    488         str_cpy(info->model_name, NIC_MODEL_MAX_LENGTH, "RTL8169");
     503        nic_t *nic_data = nic_get_from_ddf_fun(fun);
     504        rtl8169_t *rtl8169 = nic_get_specific(nic_data);
     505
     506        str_cpy(info->vendor_name, NIC_VENDOR_MAX_LENGTH, "Unknown");
     507        str_cpy(info->model_name, NIC_MODEL_MAX_LENGTH, "Unknown");
     508
     509        if (rtl8169->pci_vid == PCI_VID_REALTEK)
     510                str_cpy(info->vendor_name, NIC_VENDOR_MAX_LENGTH, "Realtek");
     511       
     512        if (rtl8169->pci_vid == PCI_VID_DLINK)
     513                str_cpy(info->vendor_name, NIC_VENDOR_MAX_LENGTH, "D-Link");
     514       
     515        if (rtl8169->pci_pid == 0x8168)
     516                str_cpy(info->model_name, NIC_MODEL_MAX_LENGTH, "RTL8168");
     517       
     518        if (rtl8169->pci_pid == 0x8169)
     519                str_cpy(info->model_name, NIC_MODEL_MAX_LENGTH, "RTL8169");
     520
     521        if (rtl8169->pci_pid == 0x8110)
     522                str_cpy(info->model_name, NIC_MODEL_MAX_LENGTH, "RTL8110");
    489523
    490524        return EOK;
     
    541575        bmcr &= ~(BMCR_DUPLEX | BMCR_SPD_100 | BMCR_SPD_1000);
    542576       
     577        /* Disable autonegotiation */
     578        bmcr &= ~BMCR_AN_ENABLE;
     579
    543580        if (duplex == NIC_CM_FULL_DUPLEX)
    544581                bmcr |= BMCR_DUPLEX;
     
    609646static int rtl8169_autoneg_restart(ddf_fun_t *fun)
    610647{
     648        rtl8169_t *rtl8169 = nic_get_specific(nic_get_from_ddf_fun(fun));
     649        uint16_t bmcr = rtl8169_mii_read(rtl8169, MII_BMCR);
     650
     651        bmcr |= BMCR_AN_ENABLE;
     652        rtl8169_mii_write(rtl8169, MII_BMCR, bmcr);
    611653        return EOK;
    612654}
     
    696738        /* Configure Receive Control Register */
    697739        uint32_t rcr = pio_read_32(rtl8169->regs + RCR);
    698         rcr |= RCR_ACCEPT_ALL_PHYS | RCR_ACCEPT_PHYS_MATCH \
    699             | RCR_ACCEPT_BROADCAST | RCR_ACCEPT_ERROR \
    700             | RCR_ACCEPT_RUNT;
     740        rtl8169->rcr_ucast = RCR_ACCEPT_PHYS_MATCH;
     741        rcr |= RCR_ACCEPT_PHYS_MATCH | RCR_ACCEPT_ERROR | RCR_ACCEPT_RUNT;
    701742        pio_write_32(rtl8169->regs + RCR, rcr);
    702743        pio_write_16(rtl8169->regs + RMS, BUFFER_SIZE);
    703744
    704         ddf_msg(LVL_NOTE, "RCR: 0x%08x", pio_read_32(rtl8169->regs + RCR));
    705 
    706 
    707745        pio_write_16(rtl8169->regs + IMR, 0xffff);
    708         nic_enable_interrupt(nic_data, rtl8169->irq);
     746        irc_enable_interrupt(rtl8169->irq);
    709747
    710748        return EOK;
     
    756794}
    757795
     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
    758817static int rtl8169_unicast_set(nic_t *nic_data, nic_unicast_mode_t mode,
    759818    const nic_address_t *addr, size_t addr_count)
    760819{
     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);
    761866        return EOK;
    762867}
     
    765870    const nic_address_t *addr, size_t addr_count)
    766871{
     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);
    767910        return EOK;
    768911}
     
    770913static int rtl8169_broadcast_set(nic_t *nic_data, nic_broadcast_mode_t mode)
    771914{
     915        rtl8169_t *rtl8169 = nic_get_specific(nic_data);
     916       
     917        /* Configure Receive Control Register */
     918        uint32_t rcr = pio_read_32(rtl8169->regs + RCR);
     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
     933        pio_write_32(rtl8169->regs + RCR, rcr);
     934        ddf_msg(LVL_DEBUG," new RCR value: 0x%08x", rcr);
     935
    772936        return EOK;
    773937}
     
    779943        rtl8169_t *rtl8169 = nic_get_specific(nic_data);
    780944        rtl8169_descr_t *descr;
    781 
    782         ddf_msg(LVL_NOTE, "rtl8169_transmit_done()");
     945        int sent = 0;
     946
     947        ddf_msg(LVL_DEBUG, "rtl8169_transmit_done()");
    783948
    784949        fibril_mutex_lock(&rtl8169->tx_lock);
     
    791956                descr->control &= (~CONTROL_OWN);
    792957                write_barrier();
    793                 ddf_msg(LVL_NOTE, "TX status for descr %d: 0x%08x", tail, descr->control);
     958                ddf_msg(LVL_DEBUG, "TX status for descr %d: 0x%08x", tail, descr->control);
    794959       
    795960                tail = (tail + 1) % TX_BUFFERS_COUNT;
    796         }
     961                sent++;
     962        }
     963
     964        if (sent != 0)
     965                nic_set_tx_busy(nic_data, 0);
    797966
    798967        rtl8169->tx_tail = tail;
     
    812981        int frame_size;
    813982
    814         ddf_msg(LVL_NOTE, "rtl8169_receive_done()");
     983        ddf_msg(LVL_DEBUG, "rtl8169_receive_done()");
    815984
    816985        fibril_mutex_lock(&rtl8169->rx_lock);
     
    825994
    826995                if (descr->control & RXSTATUS_RES) {
    827                         ddf_msg(LVL_NOTE, "error at slot %d: 0x%08x\n", tail, descr->control);
     996                        ddf_msg(LVL_WARN, "error at slot %d: 0x%08x\n", tail, descr->control);
    828997                        tail = (tail + 1) % RX_BUFFERS_COUNT;
    829998                        continue;
     
    8341003               
    8351004                if (descr->control & CONTROL_LS) {
    836 
    837                         ddf_msg(LVL_NOTE, "received message at slot %d, control 0x%08x", tail, descr->control);
     1005                        ddf_msg(LVL_DEBUG, "received message at slot %d, control 0x%08x", tail, descr->control);
    8381006
    8391007                        if (fsidx != tail)
     
    8601028}
    8611029
    862 static void rtl8169_irq_handler(ddf_dev_t *dev, ipc_callid_t iid,
    863     ipc_call_t *icall)
     1030static void rtl8169_irq_handler(ipc_callid_t iid, ipc_call_t *icall,
     1031    ddf_dev_t *dev)
    8641032{
    8651033        assert(dev);
     
    8701038        rtl8169_t *rtl8169 = nic_get_specific(nic_data);
    8711039
    872         ddf_msg(LVL_NOTE, "rtl8169_irq_handler(): isr=0x%04x", isr);
     1040        ddf_msg(LVL_DEBUG, "rtl8169_irq_handler(): isr=0x%04x", isr);
    8731041        pio_write_16(rtl8169->regs + IMR, 0xffff);
    8741042
     
    8881056                }
    8891057
     1058                /* Receive underrun */
     1059                if (isr & INT_RXOVW) {
     1060                        /* just ack.. */
     1061                        pio_write_16(rtl8169->regs + ISR, INT_RXOVW);
     1062                }
     1063
    8901064                if (isr & INT_SERR) {
    8911065                        ddf_msg(LVL_ERROR, "System error interrupt");
     
    9201094        fibril_mutex_lock(&rtl8169->tx_lock);
    9211095
    922         ddf_msg(LVL_NOTE, "send_frame: size: %zu, tx_head=%d tx_tail=%d",
     1096        ddf_msg(LVL_DEBUG, "send_frame: size: %zu, tx_head=%d tx_tail=%d",
    9231097            size, rtl8169->tx_head, rtl8169->tx_tail);
    9241098
     
    9431117        prev = &rtl8169->tx_ring[(head - 1) % TX_BUFFERS_COUNT];
    9441118
    945         ddf_msg(LVL_NOTE, "current_descr=%p, prev_descr=%p", descr, prev);
     1119        ddf_msg(LVL_DEBUG, "current_descr=%p, prev_descr=%p", descr, prev);
    9461120
    9471121        descr->control = CONTROL_OWN | CONTROL_FS | CONTROL_LS;
Note: See TracChangeset for help on using the changeset viewer.