--- dynamips-0.2.11-source.orig/common/dev_gt.c 2014-03-02 15:22:17.881753020 +0100 +++ dynamips-0.2.11-source.patched/common/dev_gt.c 2014-03-02 15:15:55.467367795 +0100 @@ -2093,8 +2093,8 @@ int queue) { u_char pkt[GT_MAX_PKT_SIZE],*pkt_ptr; - struct sdma_desc txd0,ctxd,*ptxd; - m_uint32_t tx_start,tx_current; + struct sdma_desc ctxd; + m_uint32_t tx_current; m_uint32_t len,tot_len; int abort = FALSE; @@ -2106,17 +2106,29 @@ return(FALSE); /* Copy the current txring descriptor */ - tx_start = tx_current = port->tx_current[queue]; + tx_current = port->tx_current[queue]; - if (!tx_start) + if (!tx_current) return(FALSE); - ptxd = &txd0; - gt_sdma_desc_read(d,tx_start,ptxd); + gt_sdma_desc_read(d,tx_current,&ctxd); /* If we don't own the first descriptor, we cannot transmit */ - if (!(txd0.cmd_stat & GT_TXDESC_OWN)) + if (!(ctxd.cmd_stat & GT_TXDESC_OWN)) { + if (queue == 0) { + port->icr |= GT_ICR_TXENDL; + port->sdcmr |= GT_SDCMR_STDL; + port->sdcmr &= ~GT_SDCMR_TXDL; + + } else { + port->icr |= GT_ICR_TXENDH; + port->sdcmr |= GT_SDCMR_STDH; + port->sdcmr &= ~GT_SDCMR_TXDH; + } + + gt_eth_update_int_status(d,port); return(FALSE); + } /* Empty packet for now */ pkt_ptr = pkt; @@ -2125,43 +2137,41 @@ for(;;) { #if DEBUG_ETH_TX GT_LOG(d,"gt_eth_handle_txqueue: loop: " - "cmd_stat=0x%x, buf_size=0x%x, next_ptr=0x%x, buf_ptr=0x%x\n", - ptxd->cmd_stat,ptxd->buf_size,ptxd->next_ptr,ptxd->buf_ptr); + "tx_current=0x%08x, cmd_stat=0x%08x, buf_size=0x%08x, next_ptr=0x%08x, buf_ptr=0x%08x\n", + tx_current, ctxd.cmd_stat, ctxd.buf_size, ctxd.next_ptr, ctxd.buf_ptr); #endif - if (!(ptxd->cmd_stat & GT_TXDESC_OWN)) { + if (!(ctxd.cmd_stat & GT_TXDESC_OWN)) { GT_LOG(d,"gt_eth_handle_txqueue: descriptor not owned!\n"); abort = TRUE; break; } /* Copy packet data to the buffer */ - len = (ptxd->buf_size & GT_TXDESC_BC_MASK) >> GT_TXDESC_BC_SHIFT; + len = (ctxd.buf_size & GT_TXDESC_BC_MASK) >> GT_TXDESC_BC_SHIFT; - physmem_copy_from_vm(d->vm,pkt_ptr,ptxd->buf_ptr,len); + physmem_copy_from_vm(d->vm,pkt_ptr,ctxd.buf_ptr,len); pkt_ptr += len; tot_len += len; - /* Clear the OWN bit if this is not the first descriptor */ - if (!(ptxd->cmd_stat & GT_TXDESC_F)) { - ptxd->cmd_stat &= ~GT_TXDESC_OWN; - physmem_copy_u32_to_vm(d->vm,tx_current,ptxd->cmd_stat); + /* Clear the OWN bit if this is not the last descriptor */ + if (!(ctxd.cmd_stat & GT_TXDESC_L)) { + ctxd.cmd_stat &= ~GT_TXDESC_OWN; + physmem_copy_u32_to_vm(d->vm,tx_current+4,ctxd.cmd_stat); } - tx_current = ptxd->next_ptr; - /* Last descriptor or no more desc available ? */ - if (ptxd->cmd_stat & GT_TXDESC_L) + if (ctxd.cmd_stat & GT_TXDESC_L) break; - if (!tx_current) { + if (!(ctxd.next_ptr)) { abort = TRUE; break; } /* Fetch the next descriptor */ + tx_current = ctxd.next_ptr; gt_sdma_desc_read(d,tx_current,&ctxd); - ptxd = &ctxd; } if ((tot_len != 0) && !abort) { @@ -2180,11 +2190,11 @@ port->tx_frames++; } - /* Clear the OWN flag of the first descriptor */ - txd0.cmd_stat &= ~GT_TXDESC_OWN; - physmem_copy_u32_to_vm(d->vm,tx_start+4,txd0.cmd_stat); + /* Clear the OWN flag of the last descriptor */ + ctxd.cmd_stat &= ~GT_TXDESC_OWN; + physmem_copy_u32_to_vm(d->vm,tx_current+4,ctxd.cmd_stat); - port->tx_current[queue] = tx_current; + port->tx_current[queue] = tx_current = ctxd.next_ptr; /* Notify host about transmitted packet */ if (queue == 0)