Changes in uspace/drv/nic/rtl8169/driver.c [96e368a:a4666a9] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/nic/rtl8169/driver.c
r96e368a ra4666a9 27 27 */ 28 28 29 #define _DDF_DATA_IMPLANT30 31 29 #include <assert.h> 32 30 #include <errno.h> 33 31 #include <align.h> 34 32 #include <byteorder.h> 33 #include <irc.h> 35 34 #include <libarch/barrier.h> 36 35 … … 75 74 static int rtl8169_on_stopped(nic_t *nic_data); 76 75 static 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);76 static void rtl8169_irq_handler(ipc_callid_t iid, ipc_call_t *icall, 77 ddf_dev_t *dev); 79 78 static inline int rtl8169_register_int_handler(nic_t *nic_data); 80 79 static inline void rtl8169_get_hwaddr(rtl8169_t *rtl8169, nic_address_t *addr); … … 329 328 } 330 329 330 static 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 331 338 static int rtl8169_dev_initialize(ddf_dev_t *dev) 332 339 { … … 350 357 failed: 351 358 ddf_msg(LVL_ERROR, "The device initialization failed"); 352 // rtl8139_dev_cleanup(dev);359 rtl8169_dev_cleanup(dev); 353 360 return ret; 354 361 … … 388 395 rtl8169_t *rtl8169 = nic_get_specific(nic_data); 389 396 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 390 408 /* Map register space */ 391 409 rc = pio_enable(rtl8169->regs_phys, RTL8169_IO_SIZE, &rtl8169->regs); … … 419 437 pio_write_8(rtl8169->regs + CR, cr_value | CR_TE | CR_RE); 420 438 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 427 439 fun = ddf_fun_create(nic_get_ddf_dev(nic_data), fun_exposed, "port0"); 428 440 if (fun == NULL) { … … 433 445 nic_set_ddf_fun(nic_data, fun); 434 446 ddf_fun_set_ops(fun, &rtl8169_dev_ops); 435 ddf_fun_data_implant(fun, nic_data);436 447 437 448 rc = ddf_fun_bind(fun); … … 461 472 err_pio: 462 473 err_destroy: 463 //rtl8169_dev_cleanup(dev);474 rtl8169_dev_cleanup(dev); 464 475 return rc; 465 476 … … 473 484 int rc; 474 485 475 rtl8169_set_hwaddr(rtl8169, addr); 486 fibril_mutex_lock(&rtl8169->rx_lock); 487 fibril_mutex_lock(&rtl8169->tx_lock); 476 488 477 489 rc = nic_report_address(nic_data, addr); … … 479 491 return rc; 480 492 493 rtl8169_set_hwaddr(rtl8169, addr); 494 495 fibril_mutex_unlock(&rtl8169->rx_lock); 496 fibril_mutex_unlock(&rtl8169->tx_lock); 497 481 498 return EOK; 482 499 } … … 484 501 static int rtl8169_get_device_info(ddf_fun_t *fun, nic_device_info_t *info) 485 502 { 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"); 489 523 490 524 return EOK; … … 541 575 bmcr &= ~(BMCR_DUPLEX | BMCR_SPD_100 | BMCR_SPD_1000); 542 576 577 /* Disable autonegotiation */ 578 bmcr &= ~BMCR_AN_ENABLE; 579 543 580 if (duplex == NIC_CM_FULL_DUPLEX) 544 581 bmcr |= BMCR_DUPLEX; … … 609 646 static int rtl8169_autoneg_restart(ddf_fun_t *fun) 610 647 { 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); 611 653 return EOK; 612 654 } … … 696 738 /* Configure Receive Control Register */ 697 739 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; 701 742 pio_write_32(rtl8169->regs + RCR, rcr); 702 743 pio_write_16(rtl8169->regs + RMS, BUFFER_SIZE); 703 744 704 ddf_msg(LVL_NOTE, "RCR: 0x%08x", pio_read_32(rtl8169->regs + RCR));705 706 707 745 pio_write_16(rtl8169->regs + IMR, 0xffff); 708 nic_enable_interrupt(nic_data,rtl8169->irq);746 irc_enable_interrupt(rtl8169->irq); 709 747 710 748 return EOK; … … 756 794 } 757 795 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 */ 802 inline 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 758 817 static int rtl8169_unicast_set(nic_t *nic_data, nic_unicast_mode_t mode, 759 818 const nic_address_t *addr, size_t addr_count) 760 819 { 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); 761 866 return EOK; 762 867 } … … 765 870 const nic_address_t *addr, size_t addr_count) 766 871 { 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); 767 910 return EOK; 768 911 } … … 770 913 static int rtl8169_broadcast_set(nic_t *nic_data, nic_broadcast_mode_t mode) 771 914 { 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 772 936 return EOK; 773 937 } … … 779 943 rtl8169_t *rtl8169 = nic_get_specific(nic_data); 780 944 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()"); 783 948 784 949 fibril_mutex_lock(&rtl8169->tx_lock); … … 791 956 descr->control &= (~CONTROL_OWN); 792 957 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); 794 959 795 960 tail = (tail + 1) % TX_BUFFERS_COUNT; 796 } 961 sent++; 962 } 963 964 if (sent != 0) 965 nic_set_tx_busy(nic_data, 0); 797 966 798 967 rtl8169->tx_tail = tail; … … 812 981 int frame_size; 813 982 814 ddf_msg(LVL_ NOTE, "rtl8169_receive_done()");983 ddf_msg(LVL_DEBUG, "rtl8169_receive_done()"); 815 984 816 985 fibril_mutex_lock(&rtl8169->rx_lock); … … 825 994 826 995 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); 828 997 tail = (tail + 1) % RX_BUFFERS_COUNT; 829 998 continue; … … 834 1003 835 1004 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); 838 1006 839 1007 if (fsidx != tail) … … 860 1028 } 861 1029 862 static void rtl8169_irq_handler( ddf_dev_t *dev, ipc_callid_t iid,863 ipc_call_t *icall)1030 static void rtl8169_irq_handler(ipc_callid_t iid, ipc_call_t *icall, 1031 ddf_dev_t *dev) 864 1032 { 865 1033 assert(dev); … … 870 1038 rtl8169_t *rtl8169 = nic_get_specific(nic_data); 871 1039 872 ddf_msg(LVL_ NOTE, "rtl8169_irq_handler(): isr=0x%04x", isr);1040 ddf_msg(LVL_DEBUG, "rtl8169_irq_handler(): isr=0x%04x", isr); 873 1041 pio_write_16(rtl8169->regs + IMR, 0xffff); 874 1042 … … 888 1056 } 889 1057 1058 /* Receive underrun */ 1059 if (isr & INT_RXOVW) { 1060 /* just ack.. */ 1061 pio_write_16(rtl8169->regs + ISR, INT_RXOVW); 1062 } 1063 890 1064 if (isr & INT_SERR) { 891 1065 ddf_msg(LVL_ERROR, "System error interrupt"); … … 920 1094 fibril_mutex_lock(&rtl8169->tx_lock); 921 1095 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", 923 1097 size, rtl8169->tx_head, rtl8169->tx_tail); 924 1098 … … 943 1117 prev = &rtl8169->tx_ring[(head - 1) % TX_BUFFERS_COUNT]; 944 1118 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); 946 1120 947 1121 descr->control = CONTROL_OWN | CONTROL_FS | CONTROL_LS;
Note:
See TracChangeset
for help on using the changeset viewer.