Changes in uspace/drv/nic/rtl8139/driver.c [c6533a7:e777847] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/nic/rtl8139/driver.c
rc6533a7 re777847 39 39 #include <io/log.h> 40 40 #include <nic.h> 41 #include <packet_client.h> 41 42 #include <device/pci.h> 42 43 … … 45 46 #include <ipc/ns.h> 46 47 48 #include <net_checksum.h> 49 47 50 #include <str.h> 48 51 … … 53 56 /** Global mutex for work with shared irq structure */ 54 57 FIBRIL_MUTEX_INITIALIZE(irq_reg_lock); 55 56 58 /** Lock interrupt structure mutex */ 57 #define RTL8139_IRQ_STRUCT_LOCK() \ 58 fibril_mutex_lock(&irq_reg_lock) 59 59 #define RTL8139_IRQ_STRUCT_LOCK() fibril_mutex_lock(&irq_reg_lock) 60 60 /** Unlock interrupt structure mutex */ 61 #define RTL8139_IRQ_STRUCT_UNLOCK() \ 62 fibril_mutex_unlock(&irq_reg_lock) 61 #define RTL8139_IRQ_STRUCT_UNLOCK() fibril_mutex_unlock(&irq_reg_lock) 63 62 64 63 /** PCI clock frequency in kHz */ 65 #define RTL8139_PCI_FREQ_KHZ 66 67 #define RTL8139_AUTONEG_CAPS (ETH_AUTONEG_10BASE_T_HALF |\68 ETH_AUTONEG_10BASE_T_FULL | ETH_AUTONEG_100BASE_TX_HALF |\69 64 #define RTL8139_PCI_FREQ_KHZ 33000 65 66 #define RTL8139_AUTONEG_CAPS (ETH_AUTONEG_10BASE_T_HALF \ 67 | ETH_AUTONEG_10BASE_T_FULL | ETH_AUTONEG_100BASE_TX_HALF \ 68 | ETH_AUTONEG_100BASE_TX_FULL | ETH_AUTONEG_PAUSE_SYMETRIC) 70 69 71 70 /** Lock transmitter and receiver data 72 * 73 * This function shall be called whenever 74 * both transmitter and receiver locking 75 * to force safe lock ordering (deadlock prevention) 76 * 77 * @param rtl8139 RTL8139 private data 78 * 71 * This function shall be called whenever both transmitter and receiver locking 72 * to force safe lock ordering (deadlock prevention) 73 * 74 * @param rtl8139 RTL8139 private data 79 75 */ 80 76 inline static void rtl8139_lock_all(rtl8139_t *rtl8139) … … 87 83 /** Unlock transmitter and receiver data 88 84 * 89 * @param rtl8139 RTL8139 private data 90 * 85 * @param rtl8139 RTL8139 private data 91 86 */ 92 87 inline static void rtl8139_unlock_all(rtl8139_t *rtl8139) … … 157 152 } 158 153 159 /** Update the mask of accepted frames in the RCR register according to154 /** Update the mask of accepted packets in the RCR register according to 160 155 * rcr_accept_mode value in rtl8139_t 161 156 * … … 175 170 } 176 171 177 /** Fill the mask of accepted multicast frames in the card registers172 /** Fill the mask of accepted multicast packets in the card registers 178 173 * 179 174 * @param rtl8139 The rtl8139 private data … … 399 394 #define rtl8139_tbuf_busy(tsd) ((pio_read_32(tsd) & TSD_OWN) == 0) 400 395 401 /** Send framewith the hardware396 /** Send packet with the hardware 402 397 * 403 398 * note: the main_lock is locked when framework calls this function … … 417 412 ddf_msg(LVL_DEBUG, "Sending frame"); 418 413 419 if (size > RTL8139_ FRAME_MAX_LENGTH) {414 if (size > RTL8139_PACKET_MAX_LENGTH) { 420 415 ddf_msg(LVL_ERROR, "Send frame: frame too long, %zu bytes", 421 416 size); … … 442 437 fibril_mutex_unlock(&rtl8139->tx_lock); 443 438 444 /* Get address of the buffer descriptor and framedata */439 /* Get address of the buffer descriptor and packet data */ 445 440 void *tsd = rtl8139->io_port + TSD0 + tx_curr * 4; 446 441 void *buf_addr = rtl8139->tx_buff[tx_curr]; … … 463 458 pio_write_32(tsd, tsd_value); 464 459 return; 465 460 466 461 err_busy_no_inc: 467 462 err_size: … … 510 505 } 511 506 512 /** Create framestructure from the buffer data507 /** Create packet structure from the buffer data 513 508 * 514 509 * @param nic_data NIC driver data 515 510 * @param rx_buffer The receiver buffer 516 511 * @param rx_size The buffer size 517 * @param frame_start The offset where packet data start 518 * @param frame_size The size of the frame data 519 * 520 * @return The frame list node (not connected) 521 * 522 */ 523 static nic_frame_t *rtl8139_read_frame(nic_t *nic_data, 524 void *rx_buffer, size_t rx_size, size_t frame_start, size_t frame_size) 525 { 526 nic_frame_t *frame = nic_alloc_frame(nic_data, frame_size); 512 * @param packet_start The offset where packet data start 513 * @param packet_size The size of the packet data 514 * 515 * @return The packet list node (not connected) 516 */ 517 static nic_frame_t *rtl8139_read_packet(nic_t *nic_data, 518 void *rx_buffer, size_t rx_size, size_t packet_start, size_t packet_size) 519 { 520 nic_frame_t *frame = nic_alloc_frame(nic_data, packet_size); 527 521 if (! frame) { 528 ddf_msg(LVL_ERROR, "Can not allocate frame for received frame.");522 ddf_msg(LVL_ERROR, "Can not allocate frame for received packet."); 529 523 return NULL; 530 524 } 531 525 532 void *ret = rtl8139_memcpy_wrapped(frame->data, rx_buffer, frame_start, 533 RxBUF_SIZE, frame_size); 526 void *packet_data = packet_suffix(frame->packet, packet_size); 527 if (!packet_data) { 528 ddf_msg(LVL_ERROR, "Can not get the packet suffix."); 529 nic_release_frame(nic_data, frame); 530 return NULL; 531 } 532 533 void *ret = rtl8139_memcpy_wrapped(packet_data, rx_buffer, packet_start, 534 RxBUF_SIZE, packet_size); 534 535 if (ret == NULL) { 535 536 nic_release_frame(nic_data, frame); … … 567 568 } 568 569 569 /** Receive all frames in queue570 /** Receive all packets in queue 570 571 * 571 572 * @param nic_data The controller data 572 * @return The linked list of nic_frame_list_t nodes, each containing one frame573 */ 574 static nic_frame_list_t *rtl8139_ frame_receive(nic_t *nic_data)573 * @return The linked list of packet_list_t nodes, each containing one packet 574 */ 575 static nic_frame_list_t *rtl8139_packet_receive(nic_t *nic_data) 575 576 { 576 577 rtl8139_t *rtl8139 = nic_get_specific(nic_data); … … 580 581 nic_frame_list_t *frames = nic_alloc_frame_list(); 581 582 if (!frames) 582 ddf_msg(LVL_ERROR, "Can not allocate frame list for received frames.");583 ddf_msg(LVL_ERROR, "Can not allocate frame list for received packets."); 583 584 584 585 void *rx_buffer = rtl8139->rx_buff_virt; … … 604 605 while (!rtl8139_hw_buffer_empty(rtl8139)) { 605 606 void *rx_ptr = rx_buffer + rx_offset % RxBUF_SIZE; 606 uint32_t frame_header = uint32_t_le2host( *((uint32_t*)rx_ptr) );607 uint16_t size = frame_header >> 16;608 uint16_t frame_size = size - RTL8139_CRC_SIZE;609 /* received frame flags in frameheader */610 uint16_t rcs = (uint16_t) frame_header;607 uint32_t packet_header = uint32_t_le2host( *((uint32_t*)rx_ptr) ); 608 uint16_t size = packet_header >> 16; 609 uint16_t packet_size = size - RTL8139_CRC_SIZE; 610 /* received packet flags in packet header */ 611 uint16_t rcs = (uint16_t) packet_header; 611 612 612 613 if (size == RTL8139_EARLY_SIZE) { 613 /* The framecopying is still in progress, break receiving */614 /* The packet copying is still in progress, break receiving */ 614 615 ddf_msg(LVL_DEBUG, "Early threshold reached, not completely coppied"); 615 616 break; … … 617 618 618 619 /* Check if the header is valid, otherwise we are lost in the buffer */ 619 if (size == 0 || size > RTL8139_ FRAME_MAX_LENGTH) {620 if (size == 0 || size > RTL8139_PACKET_MAX_LENGTH) { 620 621 ddf_msg(LVL_ERROR, "Receiver error -> receiver reset (size: %4"PRIu16", " 621 "header 0x%4"PRIx16". Offset: %zu)", size, frame_header,622 "header 0x%4"PRIx16". Offset: %zu)", size, packet_header, 622 623 rx_offset); 623 624 goto rx_err; … … 628 629 } 629 630 630 cur_read += size + RTL_ FRAME_HEADER_SIZE;631 cur_read += size + RTL_PACKET_HEADER_SIZE; 631 632 if (cur_read > max_read) 632 633 break; 633 634 634 635 if (frames) { 635 nic_frame_t *frame = rtl8139_read_ frame(nic_data, rx_buffer,636 RxBUF_SIZE, rx_offset + RTL_ FRAME_HEADER_SIZE, frame_size);636 nic_frame_t *frame = rtl8139_read_packet(nic_data, rx_buffer, 637 RxBUF_SIZE, rx_offset + RTL_PACKET_HEADER_SIZE, packet_size); 637 638 638 639 if (frame) … … 641 642 642 643 /* Update offset */ 643 rx_offset = ALIGN_UP(rx_offset + size + RTL_ FRAME_HEADER_SIZE, 4);644 645 /* Write lesser value to prevent overflow into unread frame644 rx_offset = ALIGN_UP(rx_offset + size + RTL_PACKET_HEADER_SIZE, 4); 645 646 /* Write lesser value to prevent overflow into unread packet 646 647 * (the recomendation from the RealTech rtl8139 programming guide) 647 648 */ … … 659 660 660 661 662 irq_pio_range_t rtl8139_irq_pio_ranges[] = { 663 { 664 .base = 0, 665 .size = RTL8139_IO_SIZE 666 } 667 }; 661 668 662 669 /** Commands to deal with interrupt … … 668 675 */ 669 676 irq_cmd_t rtl8139_irq_commands[] = { 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 677 { 678 /* Get the interrupt status */ 679 .cmd = CMD_PIO_READ_16, 680 .addr = NULL, 681 .dstarg = 2 682 }, 683 { 684 .cmd = CMD_PREDICATE, 685 .value = 3, 686 .srcarg = 2 687 }, 688 { 689 /* Mark interrupts as solved */ 690 .cmd = CMD_PIO_WRITE_16, 691 .addr = NULL, 692 .value = 0xFFFF 693 }, 694 { 695 /* Disable interrupts until interrupt routine is finished */ 696 .cmd = CMD_PIO_WRITE_16, 697 .addr = NULL, 698 .value = 0x0000 699 }, 700 { 701 .cmd = CMD_ACCEPT 702 } 696 703 }; 697 704 698 705 /** Interrupt code definition */ 699 706 irq_code_t rtl8139_irq_code = { 700 .cmdcount = sizeof(rtl8139_irq_commands)/sizeof(irq_cmd_t), 707 .rangecount = sizeof(rtl8139_irq_pio_ranges) / sizeof(irq_pio_range_t), 708 .ranges = rtl8139_irq_pio_ranges, 709 .cmdcount = sizeof(rtl8139_irq_commands) / sizeof(irq_cmd_t), 701 710 .cmds = rtl8139_irq_commands 702 711 }; … … 726 735 tx_used++; 727 736 728 /* If the framewas sent */737 /* If the packet was sent */ 729 738 if (tsd_value & TSD_TOK) { 730 739 size_t size = REG_GET_VAL(tsd_value, TSD_SIZE); … … 756 765 } 757 766 758 /** Receive all frames from the buffer767 /** Receive all packets from the buffer 759 768 * 760 769 * @param rtl8139 driver private data 761 770 */ 762 static void rtl8139_receive_ frames(nic_t *nic_data)771 static void rtl8139_receive_packets(nic_t *nic_data) 763 772 { 764 773 assert(nic_data); … … 768 777 769 778 fibril_mutex_lock(&rtl8139->rx_lock); 770 nic_frame_list_t *frames = rtl8139_ frame_receive(nic_data);779 nic_frame_list_t *frames = rtl8139_packet_receive(nic_data); 771 780 fibril_mutex_unlock(&rtl8139->rx_lock); 772 781 … … 824 833 } 825 834 826 /* Check transmittion interrupts first to allow transmit next frames835 /* Check transmittion interrupts first to allow transmit next packets 827 836 * sooner 828 837 */ … … 831 840 } 832 841 if (isr & INT_ROK) { 833 rtl8139_receive_ frames(nic_data);842 rtl8139_receive_packets(nic_data); 834 843 } 835 844 if (isr & (INT_RER | INT_RXOVW | INT_FIFOOVW)) { … … 888 897 RTL8139_IRQ_STRUCT_LOCK(); 889 898 890 rtl8139_irq_code.cmds[0].addr = rtl8139->io_port + ISR; 891 rtl8139_irq_code.cmds[2].addr = rtl8139->io_port + ISR; 892 rtl8139_irq_code.cmds[3].addr = rtl8139->io_port + IMR; 899 rtl8139_irq_code.ranges[0].base = (uintptr_t) rtl8139->io_addr; 900 rtl8139_irq_code.cmds[0].addr = rtl8139->io_addr + ISR; 901 rtl8139_irq_code.cmds[2].addr = rtl8139->io_addr + ISR; 902 rtl8139_irq_code.cmds[3].addr = rtl8139->io_addr + IMR; 893 903 int rc = register_interrupt_handler(nic_get_ddf_dev(nic_data), 894 904 rtl8139->irq, rtl8139_interrupt_handler, &rtl8139_irq_code); 895 905 896 906 RTL8139_IRQ_STRUCT_UNLOCK(); … … 932 942 } 933 943 934 /** Activate the device to receive and transmit frames944 /** Activate the device to receive and transmit packets 935 945 * 936 946 * @param nic_data The nic driver data … … 1212 1222 goto failed; 1213 1223 1214 /* Set default frameacceptance */1224 /* Set default packet acceptance */ 1215 1225 rtl8139->rcr_data.ucast_mask = RTL8139_RCR_UCAST_DEFAULT; 1216 1226 rtl8139->rcr_data.mcast_mask = RTL8139_RCR_MCAST_DEFAULT; 1217 1227 rtl8139->rcr_data.bcast_mask = RTL8139_RCR_BCAST_DEFAULT; 1218 1228 rtl8139->rcr_data.defect_mask = RTL8139_RCR_DEFECT_DEFAULT; 1219 /* Set receiver early treshold to 8/16 of framelength */1229 /* Set receiver early treshold to 8/16 of packet length */ 1220 1230 rtl8139->rcr_data.rcr_base = (0x8 << RCR_ERTH_SHIFT); 1221 1231 1222 1232 ddf_msg(LVL_DEBUG, "The device is initialized"); 1223 1233 return ret; 1224 1234 1225 1235 failed: 1226 1236 ddf_msg(LVL_ERROR, "The device initialization failed"); … … 1287 1297 int rtl8139_dev_add(ddf_dev_t *dev) 1288 1298 { 1289 ddf_fun_t *fun;1290 1291 1299 assert(dev); 1292 1300 ddf_msg(LVL_NOTE, "RTL8139_dev_add %s (handle = %d)", dev->name, dev->handle); … … 1325 1333 } 1326 1334 1327 fun = ddf_fun_create(nic_get_ddf_dev(nic_data), fun_exposed, "port0"); 1328 if (fun == NULL) { 1329 ddf_msg(LVL_ERROR, "Failed creating device function"); 1330 goto err_srv; 1331 } 1332 nic_set_ddf_fun(nic_data, fun); 1333 fun->ops = &rtl8139_dev_ops; 1334 fun->driver_data = nic_data; 1335 1336 rc = ddf_fun_bind(fun); 1335 rc = nic_register_as_ddf_fun(nic_data, &rtl8139_dev_ops); 1337 1336 if (rc != EOK) { 1338 ddf_msg(LVL_ERROR, "Failed binding device function"); 1339 goto err_fun_create; 1340 } 1341 rc = ddf_fun_add_to_category(fun, DEVICE_CATEGORY_NIC); 1342 if (rc != EOK) { 1343 ddf_msg(LVL_ERROR, "Failed adding function to category"); 1344 goto err_fun_bind; 1337 ddf_msg(LVL_ERROR, "Failed to register as DDF function - error %d", rc); 1338 goto err_irq; 1345 1339 } 1346 1340 … … 1349 1343 1350 1344 return EOK; 1351 1352 err_fun_bind: 1353 ddf_fun_unbind(fun); 1354 err_fun_create: 1355 ddf_fun_destroy(fun); 1356 err_srv: 1357 /* XXX Disconnect from services */ 1345 1358 1346 err_irq: 1359 1347 unregister_interrupt_handler(dev, rtl8139->irq); … … 1498 1486 }; 1499 1487 1500 /** Check if pause frameoperations are valid in current situation1488 /** Check if pause packet operations are valid in current situation 1501 1489 * 1502 1490 * @param rtl8139 RTL8139 private structure … … 1523 1511 } 1524 1512 1525 /** Get current pause frameconfiguration1513 /** Get current pause packet configuration 1526 1514 * 1527 1515 * Values are filled with NIC_RESULT_NOT_AVAILABLE if the value has no sense in … … 1529 1517 * 1530 1518 * @param[in] fun The DDF structure of the RTL8139 1531 * @param[out] we_send Sign if local constroller sends pause frame1532 * @param[out] we_receive Sign if local constroller receives pause frame1533 * @param[out] time Time filled in pause frames. 0xFFFF in rtl81391519 * @param[out] we_send Sign if local constroller sends pause packets 1520 * @param[out] we_receive Sign if local constroller receives pause packets 1521 * @param[out] time Time filled in pause packets. 0xFFFF in rtl8139 1534 1522 * 1535 1523 * @return EOK if succeed … … 1561 1549 }; 1562 1550 1563 /** Set current pause frameconfiguration1551 /** Set current pause packet configuration 1564 1552 * 1565 1553 * @param fun The DDF structure of the RTL8139 1566 * @param allow_send Sign if local constroller sends pause frame1567 * @param allow_receive Sign if local constroller receives pause frames1554 * @param allow_send Sign if local constroller sends pause packets 1555 * @param allow_receive Sign if local constroller receives pause packets 1568 1556 * @param time Time to use, ignored (not supported by device) 1569 1557 * 1570 * @return EOK if succeed, INVAL if the pause framehas no sence1558 * @return EOK if succeed, INVAL if the pause packet has no sence 1571 1559 */ 1572 1560 static int rtl8139_pause_set(ddf_fun_t *fun, int allow_send, int allow_receive, … … 1817 1805 } 1818 1806 1819 /** Set unicast frames acceptance mode1807 /** Set unicast packets acceptance mode 1820 1808 * 1821 1809 * @param nic_data The nic device to update … … 1875 1863 } 1876 1864 1877 /** Set multicast frames acceptance mode1865 /** Set multicast packets acceptance mode 1878 1866 * 1879 1867 * @param nic_data The nic device to update … … 1920 1908 } 1921 1909 1922 /** Set broadcast frames acceptance mode1910 /** Set broadcast packets acceptance mode 1923 1911 * 1924 1912 * @param nic_data The nic device to update … … 1950 1938 } 1951 1939 1952 /** Get state of acceptance of weird frames1940 /** Get state of acceptance of weird packets 1953 1941 * 1954 1942 * @param[in] device The device to check … … 1972 1960 }; 1973 1961 1974 /** Set acceptance of weird frames1962 /** Set acceptance of weird packets 1975 1963 * 1976 1964 * @param device The device to update … … 2148 2136 } 2149 2137 2150 /** Force receiving all frames in the receive buffer2138 /** Force receiving all packets in the receive buffer 2151 2139 * 2152 2140 * @param device The device to receive
Note:
See TracChangeset
for help on using the changeset viewer.