Exemple #1
0
static void rtl8169_setup_descriptors(rtl8169 *r)
{
	int i;

	/* set up the rx/tx descriptors */
	for (i=0; i < NUM_RX_DESCRIPTORS; i++) {
		addr_t physaddr;

		physaddr = vtophys(RXBUF(r, i));
		SHOW_FLOW(2, "setup_descriptors: rx buffer at %p, addr 0x%x\n", RXBUF(r, i), physaddr);

		r->rxdesc[i].rx_buffer_low = physaddr;
		r->rxdesc[i].rx_buffer_high = physaddr >> 32;
		r->rxdesc[i].frame_len = BUFSIZE_PER_FRAME;
		r->rxdesc[i].flags = RTL_DESC_OWN | ((i == (NUM_RX_DESCRIPTORS - 1)) ? RTL_DESC_EOR : 0);
	}
	for (i=0; i < NUM_TX_DESCRIPTORS; i++) {
		addr_t physaddr;

		physaddr = vtophys(TXBUF(r, i));
		SHOW_FLOW(2, "setup_descriptors: tx buffer at %p, addr 0x%x\n", TXBUF(r, i), physaddr);

		r->txdesc[i].tx_buffer_low = physaddr;
		r->txdesc[i].tx_buffer_high = physaddr >> 32;
		r->txdesc[i].frame_len = 0; // will need to be filled in when transmitting
		r->txdesc[i].flags = (i == (NUM_TX_DESCRIPTORS - 1)) ? RTL_DESC_EOR : 0;
	}

	/* set up our index pointers */
	r->rx_idx_free = 0;
	r->rx_idx_full = 0;
	r->tx_idx_free = 0;
	r->tx_idx_full = 0;

	/* point the nic at the descriptors */
	RTL_WRITE_32(r, REG_TNPDS_LOW, r->txdesc_phys);
	RTL_WRITE_32(r, REG_TNPDS_HIGH, r->txdesc_phys >> 32);
	RTL_WRITE_32(r, REG_RDSAR_LOW, r->rxdesc_phys);
	RTL_WRITE_32(r, REG_RDSAR_HIGH, r->rxdesc_phys >> 32);
}
ssize_t rtl8169_rx(rtl8169 *r, char *buf, ssize_t buf_len)
{
    //uint32 tail;
    ssize_t len;
    int rc;
    bool release_sem = false;

    SHOW_FLOW0(3, "rtl8169_rx: entry\n");

    if(buf_len < 1500)
        return -1;

restart:
    hal_sem_acquire(&r->rx_sem);
    mutex_lock(&r->lock);

    int_disable_interrupts();
    acquire_spinlock(&r->reg_spinlock);

    /* look at the descriptor pointed to by rx_idx_free */
    if (r->rxdesc[r->rx_idx_free].flags & RTL_DESC_OWN) {
        /* for some reason it's owned by the card, wait for more packets */
        release_spinlock(&r->reg_spinlock);
        int_restore_interrupts();
        mutex_unlock(&r->lock);
        goto restart;
    }

    /* process this packet */
    len =  r->rxdesc[r->rx_idx_free].frame_len & 0x3fff;
    SHOW_FLOW(3, "rtl8169_rx: desc idx %d: len %d\n", r->rx_idx_free, len);

    if (len > buf_len) {
        rc = ERR_TOO_BIG;
        release_sem = true;
        goto out;
    }

    memcpy(buf, RXBUF(r, r->rx_idx_free), len);
    rc = len;

#if debug_level_flow >= 3
    hexdump(RXBUF(r, r->rx_idx_free), len, 0, 0);
#endif

    /* stick it back in the free list */
    r->rxdesc[r->rx_idx_free].buffer_size = BUFSIZE_PER_FRAME;
    r->rxdesc[r->rx_idx_free].flags = (r->rxdesc[r->rx_idx_free].flags & RTL_DESC_EOR) | RTL_DESC_OWN;
    inc_rx_idx_free(r);

    /* see if there are more packets pending */
    if ((r->rxdesc[r->rx_idx_free].flags & RTL_DESC_OWN) == 0)
        release_sem = true; // if so, release the rx sem so the next reader gets a shot

out:
    release_spinlock(&r->reg_spinlock);
    int_restore_interrupts();

    if(release_sem)
        hal_sem_release(&r->rx_sem);
    mutex_unlock(&r->lock);

    return rc;
}