Changeset 59b3095 in mainline for uspace/drv/nic/rtl8169/driver.c


Ignore:
Timestamp:
2014-06-02T20:53:10Z (10 years ago)
Author:
Agnieszka Tabaka <nufcia@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
be971233
Parents:
0764cc8a
Message:

Implemented DMA buffers allocation and frame sending mechanism. Buffers reclaiming is not implemented yet.

File:
1 edited

Legend:

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

    r0764cc8a r59b3095  
    209209                return EINVAL;
    210210        };
     211
    211212        if (hw_resources->io_ranges.count != 1) {
    212213                ddf_msg(LVL_ERROR, "%s device: unexpected io ranges count", ddf_dev_get_name(dev));
     
    237238        rc = dmamem_map_anonymous(TX_RING_SIZE, DMAMEM_4GiB,
    238239            AS_AREA_READ | AS_AREA_WRITE, 0, &rtl8169->tx_ring_phys,
    239             &rtl8169->tx_ring_virt);
     240            (void **)&rtl8169->tx_ring);
    240241
    241242        if (rc != EOK)
     
    245246        rc = dmamem_map_anonymous(RX_RING_SIZE, DMAMEM_4GiB,
    246247            AS_AREA_READ | AS_AREA_WRITE, 0, &rtl8169->rx_ring_phys,
    247             &rtl8169->rx_ring_virt);
     248            (void **)&rtl8169->rx_ring);
    248249
    249250        if (rc != EOK)
     
    253254        rc = dmamem_map_anonymous(TX_BUFFERS_SIZE, DMAMEM_4GiB,
    254255            AS_AREA_READ | AS_AREA_WRITE, 0, &rtl8169->tx_buff_phys,
    255             &rtl8169->tx_buff_virt);
     256            &rtl8169->tx_buff);
    256257
    257258        if (rc != EOK)
     
    261262        rc = dmamem_map_anonymous(RX_BUFFERS_SIZE, DMAMEM_4GiB,
    262263            AS_AREA_READ | AS_AREA_WRITE, 0, &rtl8169->rx_buff_phys,
    263             &rtl8169->rx_buff_virt);
     264            &rtl8169->rx_buff);
    264265
    265266        if (rc != EOK)
    266267                return rc;
     268
     269        return EOK;
    267270}
    268271
     
    521524        rtl8169_reset(rtl8169);
    522525
     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
    523536        /* Enable TX and RX */
    524537        uint8_t cr = pio_read_8(rtl8169->regs + CR);
     
    594607}
    595608
    596 
     609static 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}
    597634
    598635static void rtl8169_irq_handler(ddf_dev_t *dev, ipc_callid_t iid,
     
    601638        assert(dev);
    602639        assert(icall);
    603 
    604         ddf_msg(LVL_NOTE, "rtl8169_irq_handler()");
    605640
    606641        uint16_t isr = (uint16_t) IPC_GET_ARG2(*icall);
     
    608643        rtl8169_t *rtl8169 = nic_get_specific(nic_data);
    609644
     645        //ddf_msg(LVL_NOTE, "rtl8169_irq_handler(): isr=0x%04x", isr);
     646
    610647        /* Packet underrun or link change */
    611648        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);
    614672        pio_write_16(rtl8169->regs + IMR, 0xffff);
    615673}
     
    617675static void rtl8169_send_frame(nic_t *nic_data, void *data, size_t size)
    618676{
    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);
    620733}
    621734
Note: See TracChangeset for help on using the changeset viewer.