示例#1
0
static void
eth_write(void *opaque, hwaddr addr,
          uint64_t val64, unsigned int size)
{
    struct xlx_ethlite *s = opaque;
    unsigned int base = 0;
    uint32_t value = val64;

    addr >>= 2;
    switch (addr) 
    {
        case R_TX_CTRL0:
        case R_TX_CTRL1:
            if (addr == R_TX_CTRL1)
                base = 0x800 / 4;

            D(qemu_log("%s addr=" TARGET_FMT_plx " val=%x\n",
                       __func__, addr * 4, value));
            if ((value & (CTRL_P | CTRL_S)) == CTRL_S) {
                qemu_send_packet(qemu_get_queue(s->nic),
                                 (void *) &s->regs[base],
                                 s->regs[base + R_TX_LEN0]);
                D(qemu_log("eth_tx %d\n", s->regs[base + R_TX_LEN0]));
                if (s->regs[base + R_TX_CTRL0] & CTRL_I)
                    eth_pulse_irq(s);
            } else if ((value & (CTRL_P | CTRL_S)) == (CTRL_P | CTRL_S)) {
                memcpy(&s->conf.macaddr.a[0], &s->regs[base], 6);
                if (s->regs[base + R_TX_CTRL0] & CTRL_I)
                    eth_pulse_irq(s);
            }

            /* We are fast and get ready pretty much immediately so
               we actually never flip the S nor P bits to one.  */
            s->regs[addr] = value & ~(CTRL_P | CTRL_S);
            break;

        /* Keep these native.  */
        case R_RX_CTRL0:
        case R_RX_CTRL1:
            if (!(value & CTRL_S)) {
                qemu_flush_queued_packets(qemu_get_queue(s->nic));
            }
            /* fall through */
        case R_TX_LEN0:
        case R_TX_LEN1:
        case R_TX_GIE0:
            D(qemu_log("%s addr=" TARGET_FMT_plx " val=%x\n",
                       __func__, addr * 4, value));
            s->regs[addr] = value;
            break;

        default:
            s->regs[addr] = tswap32(value);
            break;
    }
}
示例#2
0
static void
eth_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
{
    struct xlx_ethlite *s = opaque;
    unsigned int base = 0;

    addr >>= 2;
    switch (addr) 
    {
        case R_TX_CTRL0:
        case R_TX_CTRL1:
            if (addr == R_TX_CTRL1)
                base = 0x800 / 4;

            D(qemu_log("%s addr=%x val=%x\n", __func__, addr * 4, value));
            if ((value & (CTRL_P | CTRL_S)) == CTRL_S) {
                qemu_send_packet(&s->nic->nc,
                                 (void *) &s->regs[base],
                                 s->regs[base + R_TX_LEN0]);
                D(qemu_log("eth_tx %d\n", s->regs[base + R_TX_LEN0]));
                if (s->regs[base + R_TX_CTRL0] & CTRL_I)
                    eth_pulse_irq(s);
            } else if ((value & (CTRL_P | CTRL_S)) == (CTRL_P | CTRL_S)) {
                memcpy(&s->conf.macaddr.a[0], &s->regs[base], 6);
                if (s->regs[base + R_TX_CTRL0] & CTRL_I)
                    eth_pulse_irq(s);
            }

            /* We are fast and get ready pretty much immediately so
               we actually never flip the S nor P bits to one.  */
            s->regs[addr] = value & ~(CTRL_P | CTRL_S);
            break;

        /* Keep these native.  */
        case R_TX_LEN0:
        case R_TX_LEN1:
        case R_TX_GIE0:
        case R_RX_CTRL0:
        case R_RX_CTRL1:
            D(qemu_log("%s addr=%x val=%x\n", __func__, addr * 4, value));
            s->regs[addr] = value;
            break;

        /* Packet data, make sure it stays BE.  */
        default:
            s->regs[addr] = cpu_to_be32(value);
            break;
    }
}
示例#3
0
static ssize_t eth_rx(NetClientState *nc, const uint8_t *buf, size_t size)
{
    struct xlx_ethlite *s = qemu_get_nic_opaque(nc);
    unsigned int rxbase = s->rxbuf * (0x800 / 4);

    /* DA filter.  */
    if (!(buf[0] & 0x80) && memcmp(&s->conf.macaddr.a[0], buf, 6))
        return size;

    if (s->regs[rxbase + R_RX_CTRL0] & CTRL_S) {
        D(qemu_log("ethlite lost packet %x\n", s->regs[R_RX_CTRL0]));
        return -1;
    }

    D(qemu_log("%s %zd rxbase=%x\n", __func__, size, rxbase));
    memcpy(&s->regs[rxbase + R_RX_BUF0], buf, size);

    s->regs[rxbase + R_RX_CTRL0] |= CTRL_S;
    if (s->regs[R_RX_CTRL0] & CTRL_I) {
        eth_pulse_irq(s);
    }

    /* If c_rx_pingpong was set flip buffers.  */
    s->rxbuf ^= s->c_rx_pingpong;
    return size;
}
示例#4
0
static ssize_t eth_rx(VLANClientState *nc, const uint8_t *buf, size_t size)
{
    struct xlx_ethlite *s = DO_UPCAST(NICState, nc, nc)->opaque;
    unsigned int rxbase = s->rxbuf * (0x800 / 4);
    int i;

    /* DA filter.  */
    if (!(buf[0] & 0x80) && memcmp(&s->conf.macaddr.a[0], buf, 6))
        return size;

    if (s->regs[rxbase + R_RX_CTRL0] & CTRL_S) {
        D(qemu_log("ethlite lost packet %x\n", s->regs[R_RX_CTRL0]));
        return -1;
    }

    D(qemu_log("%s %d rxbase=%x\n", __func__, size, rxbase));
    memcpy(&s->regs[rxbase + R_RX_BUF0], buf, size);

    /* Bring it into host endianess.  */
    for (i = 0; i < ((size + 3) / 4); i++) {
       uint32_t d = s->regs[rxbase + R_RX_BUF0 + i];
       s->regs[rxbase + R_RX_BUF0 + i] = be32_to_cpu(d);
    }

    s->regs[rxbase + R_RX_CTRL0] |= CTRL_S;
    if (s->regs[rxbase + R_RX_CTRL0] & CTRL_I)
        eth_pulse_irq(s);

    /* If c_rx_pingpong was set flip buffers.  */
    s->rxbuf ^= s->c_rx_pingpong;
    return size;
}
示例#5
0
static void
eth_write(void *opaque, hwaddr addr,
          uint64_t val64, unsigned int size)
{
    struct xlx_ethlite *s = opaque;
    unsigned int base = 0;
    uint32_t value = val64;

    addr >>= 2;
    switch (addr) 
    {
        case R_TX_CTRL0:
        case R_TX_CTRL1:
            if (addr == R_TX_CTRL1)
                base = 0x800 / 4;

            D(qemu_log("%s addr=" TARGET_FMT_plx " val=%x\n",
                       __func__, addr * 4, value));
            if ((value & (CTRL_P | CTRL_S)) == CTRL_S) {
                qemu_send_packet(qemu_get_queue(s->nic),
                                 (void *) &s->regs[base],
                                 s->regs[base + R_TX_LEN0]);
                D(qemu_log("eth_tx %d\n", s->regs[base + R_TX_LEN0]));
                if (s->regs[base + R_TX_CTRL0] & CTRL_I)
                    eth_pulse_irq(s);
            } else if ((value & (CTRL_P | CTRL_S)) == (CTRL_P | CTRL_S)) {
                memcpy(&s->conf.macaddr.a[0], &s->regs[base], 6);
                if (s->regs[base + R_TX_CTRL0] & CTRL_I)
                    eth_pulse_irq(s);
            }

            /* We are fast and get ready pretty much immediately so
               we actually never flip the S nor P bits to one.  */
            s->regs[addr] = value & ~(CTRL_P | CTRL_S);
            break;

        /* Keep these native.  */
        case R_RX_CTRL0:
        case R_RX_CTRL1:
            if (!(value & CTRL_S)) {
                qemu_flush_queued_packets(qemu_get_queue(s->nic));
            }
        case R_TX_LEN0:
        case R_TX_LEN1:
        case R_TX_GIE0:
            D(qemu_log("%s addr=" TARGET_FMT_plx " val=%x\n",
                       __func__, addr * 4, value));
            s->regs[addr] = value;
            break;
        case R_MDIOCTRL:
            if (((unsigned int)value & R_MDIOCTRL_MDIOSTS_MASK) != 0) {
                struct TEMAC *t = &s->TEMAC;
                unsigned int op = s->regs[R_MDIOADDR] & R_MDIOADDR_OP_MASK;
                unsigned int phyaddr = (s->regs[R_MDIOADDR] &
                    R_MDIOADDR_PHYADR_MASK) >> R_MDIOADDR_PHYADR_SHIFT;
                unsigned int regaddr = s->regs[R_MDIOADDR] &
                    R_MDIOADDR_REGADR_MASK;
                if (op) {
                    /* read PHY registers */
                    s->regs[R_MDIORD] = mdio_read_req(
                        &t->mdio_bus, phyaddr, regaddr);
                } else {
                    /* write PHY registers */
                    mdio_write_req(&t->mdio_bus, phyaddr, regaddr,
                        s->regs[R_MDIOWR]);
                }
            }
            s->regs[addr] = value;

        default:
            s->regs[addr] = tswap32(value);
            break;
    }
}