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); }
void rtl8169_xmit(rtl8169 *r, const char *ptr, ssize_t len) { //int i; #if debug_level_flow >= 3 dprintf("rtl8169_xmit dumping packet:"); hexdump(ptr, len, 0, 0); #endif restart: hal_sem_acquire(&r->tx_sem); hal_mutex_lock(&r->lock); int_disable_interrupts(); acquire_spinlock(&r->reg_spinlock); /* look at the descriptor pointed to by tx_idx_free */ if (r->txdesc[r->tx_idx_free].flags & RTL_DESC_OWN) { /* card owns this one, wait and try again later */ release_spinlock(&r->reg_spinlock); int_restore_interrupts(); mutex_unlock(&r->lock); // sem_release(r->tx_sem, 1); goto restart; } /* queue it up */ memcpy(TXBUF(r, r->tx_idx_free), ptr, len); if (len < 64) len = 64; r->txdesc[r->tx_idx_free].frame_len = len; r->txdesc[r->tx_idx_free].flags = (r->txdesc[r->tx_idx_free].flags & RTL_DESC_EOR) | RTL_DESC_FS | RTL_DESC_LS | RTL_DESC_OWN; inc_tx_idx_free(r); RTL_WRITE_8(r, REG_TPPOLL, (1<<6)); // something is on the normal queue release_spinlock(&r->reg_spinlock); int_restore_interrupts(); mutex_unlock(&r->lock); }