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 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)); }
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; }
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; }
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); } }
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; }
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 = α 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)); }