Changeset be971233 in mainline


Ignore:
Timestamp:
2014-06-09T20:44:00Z (10 years ago)
Author:
Agnieszka Tabaka <nufcia@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
e37d2f81
Parents:
59b3095
Message:

Initial receive support. Also added TX interrupt handling (still buggy as it
losts some of interrupts, though).

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

Legend:

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

    r59b3095 rbe971233  
    282282};
    283283
     284enum rtl8169_descr_rxstatus {
     285        RXSTATUS_MAR = (1 << 27),
     286        RXSTATUS_PAM = (1 << 26),
     287        RXSTATUS_BAR = (1 << 25),
     288        RXSTATUS_BOVF = (1 << 24),
     289        RXSTATUS_FOVF = (1 << 23),
     290        RXSTATUS_RWT = (1 << 22),
     291        RXSTATUS_RES = (1 << 21),
     292        RXSTATUS_RUNT = (1 << 20),
     293        RXSTATUS_CRC = (1 << 19),
     294        RXSTATUS_PID1 = (1 << 18),
     295        RXSTATUS_PID0 = (1 << 17),
     296        RXSTATUS_IPF = (1 << 16),
     297        RXSTATUS_UDPF = (1 << 15),
     298        RXSTATUS_TCPF = (1 << 14)
     299};
     300
    284301typedef struct rtl8169_descr {
    285302        uint32_t        control;
  • uspace/drv/nic/rtl8169/driver.c

    r59b3095 rbe971233  
    9393static int rtl8169_broadcast_set(nic_t *nic_data, nic_broadcast_mode_t mode);
    9494
     95static void rtl8169_rx_ring_refill(rtl8169_t *rtl8169, unsigned int first,
     96    unsigned int last);
    9597
    9698/** Network interface options for RTL8169 card driver */
     
    243245                return rc;
    244246
     247        memset(rtl8169->tx_ring, 0, TX_RING_SIZE);
     248
    245249        /* Allocate RX ring */
    246250        rc = dmamem_map_anonymous(RX_RING_SIZE, DMAMEM_4GiB,
     
    250254        if (rc != EOK)
    251255                return rc;
     256
     257        memset(rtl8169->rx_ring, 0, RX_RING_SIZE);
    252258
    253259        /* Allocate TX buffers */
     
    514520}
    515521
     522static void rtl8169_rx_ring_refill(rtl8169_t *rtl8169, unsigned int first,
     523    unsigned int last)
     524{
     525        rtl8169_descr_t *descr;
     526        uintptr_t buff_phys;
     527        unsigned int i = first;
     528
     529        for (;;) {
     530                descr = &rtl8169->rx_ring[i];
     531                buff_phys = rtl8169->rx_buff_phys + (BUFFER_SIZE * i);
     532                descr->control = BUFFER_SIZE | CONTROL_OWN;
     533                descr->buf_low = buff_phys & 0xffffffff;
     534                descr->buf_high = (buff_phys >> 32) & 0xffffffff;
     535
     536                if (i == RX_BUFFERS_COUNT - 1)
     537                        descr->control |= CONTROL_EOR;
     538
     539                if (i == last)
     540                        break;
     541
     542                i = (i + 1) % RX_BUFFERS_COUNT;
     543        }
     544}
     545
    516546static int rtl8169_on_activated(nic_t *nic_data)
    517547{
     
    526556        /* Allocate buffers */
    527557        rtl8169_allocate_buffers(rtl8169);
     558
     559        /* Initialize RX ring */
     560        rtl8169_rx_ring_refill(rtl8169, 0, RX_BUFFERS_COUNT - 1);
    528561
    529562        /* Write address of descriptor as start of TX ring */
     
    534567        rtl8169->tx_ring[15].control = CONTROL_EOR;
    535568
     569        /* Write RX ring address */
     570        pio_write_32(rtl8169->regs + RDSAR, rtl8169->rx_ring_phys & 0xffffffff);
     571        pio_write_32(rtl8169->regs + RDSAR + 4, (rtl8169->rx_ring_phys >> 32) & 0xffffffff);
     572        rtl8169->rx_head = 0;
     573        rtl8169->rx_tail = 0;
     574
     575        /* Clear pending interrupts */
     576        pio_write_16(rtl8169->regs + ISR, 0xffff);
     577
    536578        /* Enable TX and RX */
    537579        uint8_t cr = pio_read_8(rtl8169->regs + CR);
    538580        cr |= CR_TE | CR_RE;
    539581        pio_write_8(rtl8169->regs + CR, cr);
     582        pio_write_32(rtl8169->regs + MAR0, 0xffffffff);
     583        pio_write_32(rtl8169->regs + MAR0 + 4, 0xffffffff);
     584
     585        /* Configure Receive Control Register */
     586        pio_write_8(rtl8169->regs + 0x50, 0xc0);
     587        uint32_t rcr = pio_read_32(rtl8169->regs + RCR);
     588        rcr |= RCR_ACCEPT_ALL_PHYS | RCR_ACCEPT_PHYS_MATCH \
     589            | RCR_ACCEPT_BROADCAST | RCR_ACCEPT_ERROR \
     590            | RCR_ACCEPT_RUNT;
     591        pio_write_32(rtl8169->regs + RCR, rcr);
     592        pio_write_16(rtl8169->regs + RMS, BUFFER_SIZE);
     593        pio_write_8(rtl8169->regs + 0x50, 0x00);
     594
     595        ddf_msg(LVL_NOTE, "RCR: 0x%08x", pio_read_32(rtl8169->regs + RCR));
     596
    540597
    541598        pio_write_16(rtl8169->regs + IMR, 0xffff);
     
    623680        while (tail != head) {
    624681                descr = &rtl8169->tx_ring[tail];
     682                descr->control |= CONTROL_OWN;
     683                ddf_msg(LVL_NOTE, "TX status for descr %d: 0x%08x", tail, descr->control);
     684
    625685                tail = (tail + 1) % TX_BUFFERS_COUNT;
    626 
    627                 ddf_msg(LVL_NOTE, "TX status for descr %d: 0x%08x", tail, descr->control);
    628686        }
    629687
     
    631689
    632690        fibril_mutex_unlock(&rtl8169->tx_lock);
     691}
     692
     693static void rtl8169_receive_done(ddf_dev_t *dev)
     694{
     695        nic_t *nic_data = nic_get_from_ddf_dev(dev);
     696        rtl8169_t *rtl8169 = nic_get_specific(nic_data);
     697        rtl8169_descr_t *descr;
     698        nic_frame_list_t *frames = nic_alloc_frame_list();
     699        nic_frame_t *frame;
     700        void *buffer;
     701        unsigned int tail, fsidx = 0;
     702        int frame_size;
     703
     704        ddf_msg(LVL_NOTE, "rtl8169_receive_done()");
     705
     706        fibril_mutex_lock(&rtl8169->rx_lock);
     707
     708        tail = rtl8169->rx_tail;
     709
     710        for (;;) {
     711                descr = &rtl8169->rx_ring[tail];
     712
     713                if (descr->control & CONTROL_OWN)
     714                        break;
     715
     716                if (descr->control & RXSTATUS_RES) {
     717                        ddf_msg(LVL_NOTE, "error at slot %d: 0x%08x\n", tail, descr->control);
     718                        tail = (tail + 1) % RX_BUFFERS_COUNT;
     719                        continue;
     720                }
     721
     722                if (descr->control & CONTROL_FS)
     723                        fsidx = tail;
     724               
     725                if (descr->control & CONTROL_LS) {
     726
     727                        ddf_msg(LVL_NOTE, "received message at slot %d, control 0x%08x", tail, descr->control);
     728
     729                        if (fsidx != tail)
     730                                ddf_msg(LVL_WARN, "single frame spanning multiple descriptors");
     731
     732                        frame_size = descr->control & 0x1fff;
     733                        buffer = rtl8169->rx_buff + (BUFFER_SIZE * tail);
     734                        frame = nic_alloc_frame(nic_data, frame_size);
     735                        memcpy(frame->data, buffer, frame_size);
     736                        nic_frame_list_append(frames, frame);
     737                }
     738
     739                tail = (tail + 1) % RX_BUFFERS_COUNT;
     740        }
     741
     742        rtl8169_rx_ring_refill(rtl8169, rtl8169->rx_tail, tail);
     743
     744        rtl8169->rx_tail = tail;
     745
     746        fibril_mutex_unlock(&rtl8169->rx_lock);
     747
     748        nic_received_frame_list(nic_data, frames);
     749
    633750}
    634751
     
    643760        rtl8169_t *rtl8169 = nic_get_specific(nic_data);
    644761
    645         //ddf_msg(LVL_NOTE, "rtl8169_irq_handler(): isr=0x%04x", isr);
     762        ddf_msg(LVL_NOTE, "rtl8169_irq_handler(): isr=0x%04x", isr);
    646763
    647764        /* Packet underrun or link change */
     
    649766                rtl8169_link_change(dev);
    650767
    651         /* Frame(s) successfully transmitted */
    652         if (isr & INT_TOK)
    653                 rtl8169_transmit_done(dev);
    654 
    655         /* Transmit error */
    656         if (isr & INT_TER)
     768        /* Transmit notification */
     769        if (isr & (INT_TER | INT_TOK | INT_TDU))
    657770                rtl8169_transmit_done(dev);
    658771
     
    660773                ddf_msg(LVL_ERROR, "System error interrupt");
    661774
    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");
     775        if (isr & (INT_RER | INT_ROK))
     776                rtl8169_receive_done(dev);
    670777
    671778        pio_write_16(rtl8169->regs + ISR, 0xffff);
     
    690797
    691798        ddf_msg(LVL_NOTE, "send_frame()");
     799        ddf_msg(LVL_NOTE, "size: %ld", size);
    692800        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);
    694801        ddf_msg(LVL_NOTE, "tx_head=%d tx_tail=%d", rtl8169->tx_head, rtl8169->tx_tail);
    695802
     
    697804        tail = rtl8169->tx_tail;
    698805
    699         if ((tail + 1) % TX_BUFFERS_COUNT == head) {
     806        if ((head + 1) % TX_BUFFERS_COUNT == tail) {
    700807                /* Queue is full */
     808                ddf_msg(LVL_WARN, "TX queue full!");
    701809                nic_set_tx_busy(nic_data, 1);
    702810        }
     
    720828        descr->buf_low = buff_phys & 0xffffffff;
    721829        descr->buf_high = (buff_phys >> 32) & 0xffffffff;
     830
     831        if (head == TX_BUFFERS_COUNT - 1)
     832                descr->control |= CONTROL_EOR;
     833
    722834        rtl8169->tx_head = (head + 1) % TX_BUFFERS_COUNT;
    723 
    724         /* Lift EOR flag from previous descriptor */
    725         prev->control &= ~CONTROL_EOR;
    726835
    727836        write_barrier();
Note: See TracChangeset for help on using the changeset viewer.