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; }