Fork us on GitHub Follow us on Facebook Follow us on Twitter

Changeset 59b3095 in mainline


Ignore:
Timestamp:
2014-06-02T20:53:10Z (6 years ago)
Author:
Agnieszka Tabaka <nufcia@…>
Branches:
master
Children:
be971233
Parents:
0764cc8a
Message:

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

Location:
uspace/drv/nic/rtl8169
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • uspace/drv/nic/rtl8169/defs.h

    r0764cc8a r59b3095  
    4242/** Size of RTL8169 registers address space */
    4343#define RTL8169_IO_SIZE  256
     44
     45#define RTL8169_FRAME_MAX_LENGTH        1518
    4446
    4547/** Registers of RTL8169 family card offsets from the memory address base */
     
    254256};
    255257
    256 struct rtl8169_descr {
     258enum 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
     265enum 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
     276enum 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
     284typedef struct rtl8169_descr {
    257285        uint32_t        control;
    258286        uint32_t        vlan;
    259287        uint32_t        buf_low;
    260288        uint32_t        buf_high;
    261 };
     289} rtl8169_descr_t;
    262290
    263291#endif
  • 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
  • uspace/drv/nic/rtl8169/driver.h

    r0764cc8a r59b3095  
    4040#define TX_BUFFERS_COUNT        16
    4141#define RX_BUFFERS_COUNT        16
     42#define BUFFER_SIZE             2048
    4243
    4344#define TX_RING_SIZE            (sizeof(rtl8169_descr_t) * TX_BUFFERS_COUNT)
    4445#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)
    4548
    4649/** RTL8139 device data */
     
    5659        /** TX ring */
    5760        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;
    5964        /** RX ring */
    6065        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;
    6269        /** TX buffers */
    6370        uintptr_t tx_buff_phys;
    64         void *tx_buff_virt;
     71        void *tx_buff;
    6572        /** RX buffers */
    6673        uintptr_t rx_buff_phys;
     
    7683        size_t tx_used;
    7784
    78         /** Buffer for receiving frames */
    79         uintptr_t rx_buff_phys;
    80         void *rx_buff_virt;
    81 
    8285        /** Lock for receiver */
    8386        fibril_mutex_t rx_lock;
Note: See TracChangeset for help on using the changeset viewer.