static void mcf_fec_do_tx(mcf_fec_state *s) { uint32_t addr; mcf_fec_bd bd; int frame_size; int len; uint8_t frame[FEC_MAX_FRAME_SIZE]; uint8_t *ptr; DPRINTF("do_tx\n"); ptr = frame; frame_size = 0; addr = s->tx_descriptor; while (1) { mcf_fec_read_bd(&bd, addr); DPRINTF("tx_bd %x flags %04x len %d data %08x\n", addr, bd.flags, bd.length, bd.data); if ((bd.flags & FEC_BD_R) == 0) { /* Run out of descriptors to transmit. */ break; } len = bd.length; if (frame_size + len > FEC_MAX_FRAME_SIZE) { len = FEC_MAX_FRAME_SIZE - frame_size; s->eir |= FEC_INT_BABT; } cpu_physical_memory_read(bd.data, ptr, len); ptr += len; frame_size += len; if (bd.flags & FEC_BD_L) { /* Last buffer in frame. */ DPRINTF("Sending packet\n"); qemu_send_packet(qemu_get_queue(s->nic), frame, len); ptr = frame; frame_size = 0; s->eir |= FEC_INT_TXF; } s->eir |= FEC_INT_TXB; bd.flags &= ~FEC_BD_R; /* Write back the modified descriptor. */ mcf_fec_write_bd(&bd, addr); /* Advance to the next descriptor. */ if ((bd.flags & FEC_BD_W) != 0) { addr = s->etdsr; } else { addr += 8; } } s->tx_descriptor = addr; }