Beispiel #1
0
static void amdvi_log_event(AMDVIState *s, uint64_t *evt)
{
    /* event logging not enabled */
    if (!s->evtlog_enabled || amdvi_test_mask(s, AMDVI_MMIO_STATUS,
        AMDVI_MMIO_STATUS_EVT_OVF)) {
        return;
    }

    /* event log buffer full */
    if (s->evtlog_tail >= s->evtlog_len) {
        amdvi_assign_orq(s, AMDVI_MMIO_STATUS, AMDVI_MMIO_STATUS_EVT_OVF);
        /* generate interrupt */
        amdvi_generate_msi_interrupt(s);
        return;
    }

    if (dma_memory_write(&address_space_memory, s->evtlog + s->evtlog_tail,
        &evt, AMDVI_EVENT_LEN)) {
        trace_amdvi_evntlog_fail(s->evtlog, s->evtlog_tail);
    }

    s->evtlog_tail += AMDVI_EVENT_LEN;
    amdvi_assign_orq(s, AMDVI_MMIO_STATUS, AMDVI_MMIO_STATUS_COMP_INT);
    amdvi_generate_msi_interrupt(s);
}
Beispiel #2
0
static void ftgmac100_write_bd(Ftgmac100Desc *bd, dma_addr_t addr)
{
    Ftgmac100Desc lebd;
    lebd.des0 = cpu_to_le32(bd->des0);
    lebd.des1 = cpu_to_le32(bd->des1);
    lebd.des2 = cpu_to_le32(bd->des2);
    lebd.des3 = cpu_to_le32(bd->des3);
    dma_memory_write(&address_space_memory, addr, &lebd, sizeof(lebd));
}
Beispiel #3
0
static MemTxResult queue_write(SMMUQueue *q, void *data)
{
    dma_addr_t addr = Q_PROD_ENTRY(q);
    MemTxResult ret;

    ret = dma_memory_write(&address_space_memory, addr, data, q->entry_size);
    if (ret != MEMTX_OK) {
        return ret;
    }

    queue_prod_incr(q);
    return MEMTX_OK;
}
Beispiel #4
0
static void amdvi_generate_msi_interrupt(AMDVIState *s)
{
    MSIMessage msg = {};
    MemTxAttrs attrs = {
        .requester_id = pci_requester_id(&s->pci.dev)
    };

    if (msi_enabled(&s->pci.dev)) {
        msg = msi_get_message(&s->pci.dev, 0);
        address_space_stl_le(&address_space_memory, msg.address, msg.data,
                             attrs, NULL);
    }
}

static void amdvi_log_event(AMDVIState *s, uint64_t *evt)
{
    /* event logging not enabled */
    if (!s->evtlog_enabled || amdvi_test_mask(s, AMDVI_MMIO_STATUS,
        AMDVI_MMIO_STATUS_EVT_OVF)) {
        return;
    }

    /* event log buffer full */
    if (s->evtlog_tail >= s->evtlog_len) {
        amdvi_assign_orq(s, AMDVI_MMIO_STATUS, AMDVI_MMIO_STATUS_EVT_OVF);
        /* generate interrupt */
        amdvi_generate_msi_interrupt(s);
        return;
    }

    if (dma_memory_write(&address_space_memory, s->evtlog + s->evtlog_tail,
        &evt, AMDVI_EVENT_LEN)) {
        trace_amdvi_evntlog_fail(s->evtlog, s->evtlog_tail);
    }

    s->evtlog_tail += AMDVI_EVENT_LEN;
    amdvi_assign_orq(s, AMDVI_MMIO_STATUS, AMDVI_MMIO_STATUS_COMP_INT);
    amdvi_generate_msi_interrupt(s);
}

static void amdvi_setevent_bits(uint64_t *buffer, uint64_t value, int start,
                                int length)
{
    int index = start / 64, bitpos = start % 64;
    uint64_t mask = MAKE_64BIT_MASK(start, length);
    buffer[index] &= ~mask;
    buffer[index] |= (value << bitpos) & mask;
}
Beispiel #5
0
static void generic_loader_reset(void *opaque)
{
    GenericLoaderState *s = GENERIC_LOADER(opaque);

    if (s->set_pc) {
        CPUClass *cc = CPU_GET_CLASS(s->cpu);
        cpu_reset(s->cpu);
        if (cc) {
            cc->set_pc(s->cpu, s->addr);
        }
    }

    if (s->data_len) {
        assert(s->data_len < sizeof(s->data));
        dma_memory_write(s->cpu->as, s->addr, &s->data, s->data_len);
    }
}
Beispiel #6
0
static ssize_t ftgmac100_receive(NetClientState *nc, const uint8_t *buf,
                               size_t len)
{
    Ftgmac100State *s = FTGMAC100(qemu_get_nic_opaque(nc));
    Ftgmac100Desc bd;
    uint32_t flags = 0;
    uint32_t addr;
    uint32_t crc;
    uint32_t buf_addr;
    uint8_t *crc_ptr;
    unsigned int buf_len;
    size_t size = len;
    uint32_t first = FTGMAC100_RXDES0_FRS;

    DEBUG("len %d\n", (int)size);

    if (!s->rx_enabled) {
        qemu_log_mask(LOG_GUEST_ERROR, "%s: Unexpected packet\n", __func__);
        return 0;
    }

    /* FIXME: Pad short packets.  */

    /* 4 bytes for the CRC.  */
    size += 4;
    crc = cpu_to_be32(crc32(~0, buf, size));
    crc_ptr = (uint8_t *) &crc;

    /* Huge frames are truncted.  */
    if (size > FTGMAC100_MAX_FRAME_SIZE(s)) {
        size = FTGMAC100_MAX_FRAME_SIZE(s);
        qemu_log_mask(LOG_GUEST_ERROR, "%s: frame too big : %zd bytes\n",
                      __func__, size);
        flags |= FTGMAC100_RXDES0_FTL | FTGMAC100_RXDES0_RX_ERR;
    }

    if (packet_is_broadcast(buf)) {
        flags |= FTGMAC100_RXDES0_BROADCAST;
    }

    addr = s->rx_descriptor;
    while (size > 0) {
        ftgmac100_read_bd(&bd, addr);
        if (bd.des0 & FTGMAC100_RXDES0_RXPKT_RDY) {
            /* No descriptors available.  Bail out.  */
            /*
             * FIXME: This is wrong. We should probably either
             * save the remainder for when more RX buffers are
             * available, or flag an error.
             */
            qemu_log_mask(LOG_GUEST_ERROR, "%s: Lost end of frame\n",
                          __func__);
            s->isr |= FTGMAC100_INT_NO_RXBUF;
            break;
        }
        buf_len = (size <= s->rbsr) ? size : s->rbsr;
        bd.des0 |= buf_len & 0x3fff;
        size -= buf_len;

        /* The last 4 bytes are the CRC.  */
        if (size < 4) {
            buf_len += size - 4;
        }
        buf_addr = bd.des3;
        dma_memory_write(&address_space_memory, buf_addr, buf, buf_len);
        buf += buf_len;
        if (size < 4) {
            dma_memory_write(&address_space_memory, buf_addr + buf_len,
                             crc_ptr, 4 - size);
            crc_ptr += 4 - size;
        }

        bd.des0 |= first | FTGMAC100_RXDES0_RXPKT_RDY;
        first = 0;
        if (size == 0) {
            /* Last buffer in frame.  */
            bd.des0 |= flags | FTGMAC100_RXDES0_LRS;
            DEBUG("rx frame flags %04x\n", bd.des0);
            s->isr |= FTGMAC100_INT_RPKT_BUF;
        } else {
            s->isr |= FTGMAC100_INT_RPKT_FIFO;
        }
        ftgmac100_write_bd(&bd, addr);
        if (bd.des0 & ftgmac100_rxdes0_edorr(s)) {
            addr = s->rx_ring;
        } else {
            addr += sizeof(Ftgmac100Desc);
        }
    }
    s->rx_descriptor = addr;

    ftgmac100_enable_rx(s);
    ftgmac100_update_irq(s);
    return len;
}
Beispiel #7
0
static void bcm2835_property_mbox_push(BCM2835PropertyState *s, uint32_t value)
{
    uint32_t tag;
    uint32_t bufsize;
    uint32_t tot_len;
    size_t resplen;
    uint32_t tmp;
    int n;
    uint32_t offset, length, color;
    uint32_t xres, yres, xoffset, yoffset, bpp, pixo, alpha;
    uint32_t *newxres = NULL, *newyres = NULL, *newxoffset = NULL,
        *newyoffset = NULL, *newbpp = NULL, *newpixo = NULL, *newalpha = NULL;

    value &= ~0xf;

    s->addr = value;

    tot_len = ldl_le_phys(&s->dma_as, value);

    /* @(addr + 4) : Buffer response code */
    value = s->addr + 8;
    while (value + 8 <= s->addr + tot_len) {
        tag = ldl_le_phys(&s->dma_as, value);
        bufsize = ldl_le_phys(&s->dma_as, value + 4);
        /* @(value + 8) : Request/response indicator */
        resplen = 0;
        switch (tag) {
        case 0x00000000: /* End tag */
            break;
        case 0x00000001: /* Get firmware revision */
            stl_le_phys(&s->dma_as, value + 12, 346337);
            resplen = 4;
            break;
        case 0x00010001: /* Get board model */
            qemu_log_mask(LOG_UNIMP,
                          "bcm2835_property: %x get board model NYI\n", tag);
            resplen = 4;
            break;
        case 0x00010002: /* Get board revision */
            stl_le_phys(&s->dma_as, value + 12, s->board_rev);
            resplen = 4;
            break;
        case 0x00010003: /* Get board MAC address */
            resplen = sizeof(s->macaddr.a);
            dma_memory_write(&s->dma_as, value + 12, s->macaddr.a, resplen);
            break;
        case 0x00010004: /* Get board serial */
            qemu_log_mask(LOG_UNIMP,
                          "bcm2835_property: %x get board serial NYI\n", tag);
            resplen = 8;
            break;
        case 0x00010005: /* Get ARM memory */
            /* base */
            stl_le_phys(&s->dma_as, value + 12, 0);
            /* size */
            stl_le_phys(&s->dma_as, value + 16, s->fbdev->vcram_base);
            resplen = 8;
            break;
        case 0x00010006: /* Get VC memory */
            /* base */
            stl_le_phys(&s->dma_as, value + 12, s->fbdev->vcram_base);
            /* size */
            stl_le_phys(&s->dma_as, value + 16, s->fbdev->vcram_size);
            resplen = 8;
            break;
        case 0x00028001: /* Set power state */
            /* Assume that whatever device they asked for exists,
             * and we'll just claim we set it to the desired state
             */
            tmp = ldl_le_phys(&s->dma_as, value + 16);
            stl_le_phys(&s->dma_as, value + 16, (tmp & 1));
            resplen = 8;
            break;

        /* Clocks */

        case 0x00030001: /* Get clock state */
            stl_le_phys(&s->dma_as, value + 16, 0x1);
            resplen = 8;
            break;

        case 0x00038001: /* Set clock state */
            qemu_log_mask(LOG_UNIMP,
                          "bcm2835_property: %x set clock state NYI\n", tag);
            resplen = 8;
            break;

        case 0x00030002: /* Get clock rate */
        case 0x00030004: /* Get max clock rate */
        case 0x00030007: /* Get min clock rate */
            switch (ldl_le_phys(&s->dma_as, value + 12)) {
            case 1: /* EMMC */
                stl_le_phys(&s->dma_as, value + 16, 50000000);
                break;
            case 2: /* UART */
                stl_le_phys(&s->dma_as, value + 16, 3000000);
                break;
            default:
                stl_le_phys(&s->dma_as, value + 16, 700000000);
                break;
            }
            resplen = 8;
            break;

        case 0x00038002: /* Set clock rate */
        case 0x00038004: /* Set max clock rate */
        case 0x00038007: /* Set min clock rate */
            qemu_log_mask(LOG_UNIMP,
                          "bcm2835_property: %x set clock rates NYI\n", tag);
            resplen = 8;
            break;

        /* Temperature */

        case 0x00030006: /* Get temperature */
            stl_le_phys(&s->dma_as, value + 16, 25000);
            resplen = 8;
            break;

        case 0x0003000A: /* Get max temperature */
            stl_le_phys(&s->dma_as, value + 16, 99000);
            resplen = 8;
            break;

        /* Frame buffer */

        case 0x00040001: /* Allocate buffer */
            stl_le_phys(&s->dma_as, value + 12, s->fbdev->base);
            stl_le_phys(&s->dma_as, value + 16, s->fbdev->size);
            resplen = 8;
            break;
        case 0x00048001: /* Release buffer */
            resplen = 0;
            break;
        case 0x00040002: /* Blank screen */
            resplen = 4;
            break;
        case 0x00040003: /* Get display width/height */
        case 0x00040004:
            stl_le_phys(&s->dma_as, value + 12, s->fbdev->xres);
            stl_le_phys(&s->dma_as, value + 16, s->fbdev->yres);
            resplen = 8;
            break;
        case 0x00044003: /* Test display width/height */
        case 0x00044004:
            resplen = 8;
            break;
        case 0x00048003: /* Set display width/height */
        case 0x00048004:
            xres = ldl_le_phys(&s->dma_as, value + 12);
            newxres = &xres;
            yres = ldl_le_phys(&s->dma_as, value + 16);
            newyres = &yres;
            resplen = 8;
            break;
        case 0x00040005: /* Get depth */
            stl_le_phys(&s->dma_as, value + 12, s->fbdev->bpp);
            resplen = 4;
            break;
        case 0x00044005: /* Test depth */
            resplen = 4;
            break;
        case 0x00048005: /* Set depth */
            bpp = ldl_le_phys(&s->dma_as, value + 12);
            newbpp = &bpp;
            resplen = 4;
            break;
        case 0x00040006: /* Get pixel order */
            stl_le_phys(&s->dma_as, value + 12, s->fbdev->pixo);
            resplen = 4;
            break;
        case 0x00044006: /* Test pixel order */
            resplen = 4;
            break;
        case 0x00048006: /* Set pixel order */
            pixo = ldl_le_phys(&s->dma_as, value + 12);
            newpixo = &pixo;
            resplen = 4;
            break;
        case 0x00040007: /* Get alpha */
            stl_le_phys(&s->dma_as, value + 12, s->fbdev->alpha);
            resplen = 4;
            break;
        case 0x00044007: /* Test pixel alpha */
            resplen = 4;
            break;
        case 0x00048007: /* Set alpha */
            alpha = ldl_le_phys(&s->dma_as, value + 12);
            newalpha = &alpha;
            resplen = 4;
            break;
        case 0x00040008: /* Get pitch */
            stl_le_phys(&s->dma_as, value + 12, s->fbdev->pitch);
            resplen = 4;
            break;
        case 0x00040009: /* Get virtual offset */
            stl_le_phys(&s->dma_as, value + 12, s->fbdev->xoffset);
            stl_le_phys(&s->dma_as, value + 16, s->fbdev->yoffset);
            resplen = 8;
            break;
        case 0x00044009: /* Test virtual offset */
            resplen = 8;
            break;
        case 0x00048009: /* Set virtual offset */
            xoffset = ldl_le_phys(&s->dma_as, value + 12);
            newxoffset = &xoffset;
            yoffset = ldl_le_phys(&s->dma_as, value + 16);
            newyoffset = &yoffset;
            resplen = 8;
            break;
        case 0x0004000a: /* Get/Test/Set overscan */
        case 0x0004400a:
        case 0x0004800a:
            stl_le_phys(&s->dma_as, value + 12, 0);
            stl_le_phys(&s->dma_as, value + 16, 0);
            stl_le_phys(&s->dma_as, value + 20, 0);
            stl_le_phys(&s->dma_as, value + 24, 0);
            resplen = 16;
            break;
        case 0x0004800b: /* Set palette */
            offset = ldl_le_phys(&s->dma_as, value + 12);
            length = ldl_le_phys(&s->dma_as, value + 16);
            n = 0;
            while (n < length - offset) {
                color = ldl_le_phys(&s->dma_as, value + 20 + (n << 2));
                stl_le_phys(&s->dma_as,
                            s->fbdev->vcram_base + ((offset + n) << 2), color);
                n++;
            }
            stl_le_phys(&s->dma_as, value + 12, 0);
            resplen = 4;
            break;

        case 0x00060001: /* Get DMA channels */
            /* channels 2-5 */
            stl_le_phys(&s->dma_as, value + 12, 0x003C);
            resplen = 4;
            break;

        case 0x00050001: /* Get command line */
            resplen = 0;
            break;

        default:
            qemu_log_mask(LOG_GUEST_ERROR,
                          "bcm2835_property: unhandled tag %08x\n", tag);
            break;
        }

        if (tag == 0) {
            break;
        }

        stl_le_phys(&s->dma_as, value + 8, (1 << 31) | resplen);
        value += bufsize + 12;
    }

    /* Reconfigure framebuffer if required */
    if (newxres || newyres || newxoffset || newyoffset || newbpp || newpixo
        || newalpha) {
        bcm2835_fb_reconfigure(s->fbdev, newxres, newyres, newxoffset,
                               newyoffset, newbpp, newpixo, newalpha);
    }

    /* Buffer response code */
    stl_le_phys(&s->dma_as, s->addr + 4, (1 << 31));
}