Changeset 59b3095 in mainline
- Timestamp:
- 2014-06-02T20:53:10Z (10 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- be971233
- Parents:
- 0764cc8a
- Location:
- uspace/drv/nic/rtl8169
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/drv/nic/rtl8169/defs.h
r0764cc8a r59b3095 42 42 /** Size of RTL8169 registers address space */ 43 43 #define RTL8169_IO_SIZE 256 44 45 #define RTL8169_FRAME_MAX_LENGTH 1518 44 46 45 47 /** Registers of RTL8169 family card offsets from the memory address base */ … … 254 256 }; 255 257 256 struct rtl8169_descr { 258 enum rtl8169_tppoll { 259 TPPOLL_HPQ = (1 << 7), /**< Start transmit on high priority queue */ 260 TPPOLL_NPQ = (1 << 6), /**< Start transmit on normal queue */ 261 /* Bits 5-1 reserved */ 262 TPPOLL_FSWINT = (1 << 0), /** < Generate software interrupt */ 263 }; 264 265 enum rtl8169_descr_control { 266 CONTROL_OWN = (1 << 31), /**< Descriptor ownership */ 267 CONTROL_EOR = (1 << 30), /**< End Of Ring marker */ 268 CONTROL_FS = (1 << 29), /**< First Segment marker */ 269 CONTROL_LS = (1 << 28), /**< Last Segment marker */ 270 CONTROL_LGSEN = (1 << 27), /**< Large send enable */ 271 CONTROL_MSS_SHIFT = 16, 272 CONTROL_MSS_MASK = 10, 273 CONTROL_FRAMELEN_MASK = 0xffff 274 }; 275 276 enum rtl8169_descr_txstatus { 277 TXSTATUS_UNDERRUN = (1 << 25), 278 TXSTATUS_TXERRSUM = (1 << 23), 279 TXSTATUS_OWINCOL = (1 << 22), 280 TXSTATUS_LINKFAIL = (1 << 21), 281 TXSTATUS_EXCESSCOL = (1 << 20) 282 }; 283 284 typedef struct rtl8169_descr { 257 285 uint32_t control; 258 286 uint32_t vlan; 259 287 uint32_t buf_low; 260 288 uint32_t buf_high; 261 } ;289 } rtl8169_descr_t; 262 290 263 291 #endif -
uspace/drv/nic/rtl8169/driver.c
r0764cc8a r59b3095 209 209 return EINVAL; 210 210 }; 211 211 212 if (hw_resources->io_ranges.count != 1) { 212 213 ddf_msg(LVL_ERROR, "%s device: unexpected io ranges count", ddf_dev_get_name(dev)); … … 237 238 rc = dmamem_map_anonymous(TX_RING_SIZE, DMAMEM_4GiB, 238 239 AS_AREA_READ | AS_AREA_WRITE, 0, &rtl8169->tx_ring_phys, 239 &rtl8169->tx_ring_virt);240 (void **)&rtl8169->tx_ring); 240 241 241 242 if (rc != EOK) … … 245 246 rc = dmamem_map_anonymous(RX_RING_SIZE, DMAMEM_4GiB, 246 247 AS_AREA_READ | AS_AREA_WRITE, 0, &rtl8169->rx_ring_phys, 247 &rtl8169->rx_ring_virt);248 (void **)&rtl8169->rx_ring); 248 249 249 250 if (rc != EOK) … … 253 254 rc = dmamem_map_anonymous(TX_BUFFERS_SIZE, DMAMEM_4GiB, 254 255 AS_AREA_READ | AS_AREA_WRITE, 0, &rtl8169->tx_buff_phys, 255 &rtl8169->tx_buff _virt);256 &rtl8169->tx_buff); 256 257 257 258 if (rc != EOK) … … 261 262 rc = dmamem_map_anonymous(RX_BUFFERS_SIZE, DMAMEM_4GiB, 262 263 AS_AREA_READ | AS_AREA_WRITE, 0, &rtl8169->rx_buff_phys, 263 &rtl8169->rx_buff _virt);264 &rtl8169->rx_buff); 264 265 265 266 if (rc != EOK) 266 267 return rc; 268 269 return EOK; 267 270 } 268 271 … … 521 524 rtl8169_reset(rtl8169); 522 525 526 /* Allocate buffers */ 527 rtl8169_allocate_buffers(rtl8169); 528 529 /* Write address of descriptor as start of TX ring */ 530 pio_write_32(rtl8169->regs + TNPDS, rtl8169->tx_ring_phys & 0xffffffff); 531 pio_write_32(rtl8169->regs + TNPDS + 4, (rtl8169->tx_ring_phys >> 32) & 0xffffffff); 532 rtl8169->tx_head = 0; 533 rtl8169->tx_tail = 0; 534 rtl8169->tx_ring[15].control = CONTROL_EOR; 535 523 536 /* Enable TX and RX */ 524 537 uint8_t cr = pio_read_8(rtl8169->regs + CR); … … 594 607 } 595 608 596 609 static void rtl8169_transmit_done(ddf_dev_t *dev) 610 { 611 unsigned int tail, head; 612 nic_t *nic_data = nic_get_from_ddf_dev(dev); 613 rtl8169_t *rtl8169 = nic_get_specific(nic_data); 614 rtl8169_descr_t *descr; 615 616 ddf_msg(LVL_NOTE, "rtl8169_transmit_done()"); 617 618 fibril_mutex_lock(&rtl8169->tx_lock); 619 620 head = rtl8169->tx_head; 621 tail = rtl8169->tx_tail; 622 623 while (tail != head) { 624 descr = &rtl8169->tx_ring[tail]; 625 tail = (tail + 1) % TX_BUFFERS_COUNT; 626 627 ddf_msg(LVL_NOTE, "TX status for descr %d: 0x%08x", tail, descr->control); 628 } 629 630 rtl8169->tx_tail = tail; 631 632 fibril_mutex_unlock(&rtl8169->tx_lock); 633 } 597 634 598 635 static void rtl8169_irq_handler(ddf_dev_t *dev, ipc_callid_t iid, … … 601 638 assert(dev); 602 639 assert(icall); 603 604 ddf_msg(LVL_NOTE, "rtl8169_irq_handler()");605 640 606 641 uint16_t isr = (uint16_t) IPC_GET_ARG2(*icall); … … 608 643 rtl8169_t *rtl8169 = nic_get_specific(nic_data); 609 644 645 //ddf_msg(LVL_NOTE, "rtl8169_irq_handler(): isr=0x%04x", isr); 646 610 647 /* Packet underrun or link change */ 611 648 if (isr & INT_PUN) 612 rtl8169_link_change(dev); 613 649 rtl8169_link_change(dev); 650 651 /* Frame(s) successfully transmitted */ 652 if (isr & INT_TOK) 653 rtl8169_transmit_done(dev); 654 655 /* Transmit error */ 656 if (isr & INT_TER) 657 rtl8169_transmit_done(dev); 658 659 if (isr & INT_SERR) 660 ddf_msg(LVL_ERROR, "System error interrupt"); 661 662 if (isr & INT_TDU) 663 ddf_msg(LVL_ERROR, "Transmit descriptor unavailable"); 664 665 if (isr & INT_RER) 666 ddf_msg(LVL_NOTE, "RX error interrupt"); 667 668 if (isr & INT_ROK) 669 ddf_msg(LVL_NOTE, "RX OK interrupt"); 670 671 pio_write_16(rtl8169->regs + ISR, 0xffff); 614 672 pio_write_16(rtl8169->regs + IMR, 0xffff); 615 673 } … … 617 675 static void rtl8169_send_frame(nic_t *nic_data, void *data, size_t size) 618 676 { 619 677 rtl8169_descr_t *descr, *prev; 678 unsigned int head, tail; 679 void *buff; 680 uintptr_t buff_phys; 681 rtl8169_t *rtl8169 = nic_get_specific(nic_data); 682 683 if (size > RTL8169_FRAME_MAX_LENGTH) { 684 ddf_msg(LVL_ERROR, "Send frame: frame too long, %zu bytes", 685 size); 686 nic_report_send_error(nic_data, NIC_SEC_OTHER, 1); 687 } 688 689 fibril_mutex_lock(&rtl8169->tx_lock); 690 691 ddf_msg(LVL_NOTE, "send_frame()"); 692 ddf_msg(LVL_NOTE, "tx ring virtual at %p", rtl8169->tx_ring); 693 ddf_msg(LVL_NOTE, "tx ring physical at 0x%08lx", rtl8169->tx_ring_phys); 694 ddf_msg(LVL_NOTE, "tx_head=%d tx_tail=%d", rtl8169->tx_head, rtl8169->tx_tail); 695 696 head = rtl8169->tx_head; 697 tail = rtl8169->tx_tail; 698 699 if ((tail + 1) % TX_BUFFERS_COUNT == head) { 700 /* Queue is full */ 701 nic_set_tx_busy(nic_data, 1); 702 } 703 704 /* Calculate address of next free buffer and descriptor */ 705 buff = rtl8169->tx_buff + (BUFFER_SIZE * head); 706 buff_phys = rtl8169->tx_buff_phys + (BUFFER_SIZE * head); 707 708 /* Copy frame */ 709 memcpy(buff, data, size); 710 711 /* Setup descriptor */ 712 descr = &rtl8169->tx_ring[head]; 713 prev = &rtl8169->tx_ring[(head - 1) % TX_BUFFERS_COUNT]; 714 715 ddf_msg(LVL_NOTE, "current_descr=%p, prev_descr=%p", descr, prev); 716 717 descr->control = CONTROL_OWN | CONTROL_FS | CONTROL_LS; 718 descr->control |= size & 0xffff; 719 descr->vlan = 0; 720 descr->buf_low = buff_phys & 0xffffffff; 721 descr->buf_high = (buff_phys >> 32) & 0xffffffff; 722 rtl8169->tx_head = (head + 1) % TX_BUFFERS_COUNT; 723 724 /* Lift EOR flag from previous descriptor */ 725 prev->control &= ~CONTROL_EOR; 726 727 write_barrier(); 728 729 /* Notify NIC of pending packets */ 730 pio_write_8(rtl8169->regs + TPPOLL, TPPOLL_NPQ); 731 732 fibril_mutex_unlock(&rtl8169->tx_lock); 620 733 } 621 734 -
uspace/drv/nic/rtl8169/driver.h
r0764cc8a r59b3095 40 40 #define TX_BUFFERS_COUNT 16 41 41 #define RX_BUFFERS_COUNT 16 42 #define BUFFER_SIZE 2048 42 43 43 44 #define TX_RING_SIZE (sizeof(rtl8169_descr_t) * TX_BUFFERS_COUNT) 44 45 #define RX_RING_SIZE (sizeof(rtl8169_descr_t) * RX_BUFFERS_COUNT) 46 #define TX_BUFFERS_SIZE (BUFFER_SIZE * TX_BUFFERS_COUNT) 47 #define RX_BUFFERS_SIZE (BUFFER_SIZE * RX_BUFFERS_COUNT) 45 48 46 49 /** RTL8139 device data */ … … 56 59 /** TX ring */ 57 60 uintptr_t tx_ring_phys; 58 void *tx_ring_virt; 61 rtl8169_descr_t *tx_ring; 62 unsigned int tx_head; 63 unsigned int tx_tail; 59 64 /** RX ring */ 60 65 uintptr_t rx_ring_phys; 61 void *rx_ring_virt; 66 rtl8169_descr_t *rx_ring; 67 unsigned int rx_head; 68 unsigned int rx_tail; 62 69 /** TX buffers */ 63 70 uintptr_t tx_buff_phys; 64 void *tx_buff _virt;71 void *tx_buff; 65 72 /** RX buffers */ 66 73 uintptr_t rx_buff_phys; … … 76 83 size_t tx_used; 77 84 78 /** Buffer for receiving frames */79 uintptr_t rx_buff_phys;80 void *rx_buff_virt;81 82 85 /** Lock for receiver */ 83 86 fibril_mutex_t rx_lock;
Note:
See TracChangeset
for help on using the changeset viewer.