static void fw_cfg_dma_transfer(FWCfgState *s) { dma_addr_t len; FWCfgDmaAccess dma; int arch; FWCfgEntry *e; int read = 0, write = 0; dma_addr_t dma_addr; /* Reset the address before the next access */ dma_addr = s->dma_addr; s->dma_addr = 0; if (dma_memory_read(s->dma_as, dma_addr, &dma, sizeof(dma))) { stl_be_dma(s->dma_as, dma_addr + offsetof(FWCfgDmaAccess, control), FW_CFG_DMA_CTL_ERROR); return; } dma.address = be64_to_cpu(dma.address); dma.length = be32_to_cpu(dma.length); dma.control = be32_to_cpu(dma.control); if (dma.control & FW_CFG_DMA_CTL_SELECT) { fw_cfg_select(s, dma.control >> 16); }
static void ftgmac100_read_bd(Ftgmac100Desc *bd, dma_addr_t addr) { dma_memory_read(&address_space_memory, addr, bd, sizeof(*bd)); bd->des0 = le32_to_cpu(bd->des0); bd->des1 = le32_to_cpu(bd->des1); bd->des2 = le32_to_cpu(bd->des2); bd->des3 = le32_to_cpu(bd->des3); }
static void ftgmac100_do_tx(Ftgmac100State *s) { int frame_size = 0; uint8_t frame[FTGMAC100_MAX_FRAME_SIZE(s)]; uint8_t *ptr = frame; uint32_t addr; addr = ftgmac100_find_txdes(s, s->tx_descriptor); while (1) { Ftgmac100Desc bd; int len; ftgmac100_read_bd(&bd, addr); if ((bd.des0 & FTGMAC100_TXDES0_TXDMA_OWN) == 0) { /* Run out of descriptors to transmit. */ s->isr |= FTGMAC100_INT_NO_NPTXBUF; break; } len = bd.des0 & 0x3FFF; if (frame_size + len > FTGMAC100_MAX_FRAME_SIZE(s)) { qemu_log_mask(LOG_GUEST_ERROR, "%s: frame too big : %d bytes\n", __func__, len); len = FTGMAC100_MAX_FRAME_SIZE(s) - frame_size; } dma_memory_read(&address_space_memory, bd.des3, ptr, len); ptr += len; frame_size += len; if (bd.des0 & FTGMAC100_TXDES0_LTS) { /* Last buffer in frame. */ qemu_send_packet(qemu_get_queue(s->nic), frame, len); ptr = frame; frame_size = 0; if (bd.des1 & FTGMAC100_TXDES1_TXIC) { s->isr |= FTGMAC100_INT_XPKT_ETH; } } if (bd.des1 & FTGMAC100_TXDES1_TX2FIC) { s->isr |= FTGMAC100_INT_XPKT_FIFO; } bd.des0 &= ~FTGMAC100_TXDES0_TXDMA_OWN; /* Write back the modified descriptor. */ ftgmac100_write_bd(&bd, addr); /* Advance to the next descriptor. */ if (bd.des0 & ftgmac100_txdes0_edotr(s)) { addr = s->tx_ring; } else { addr += sizeof(Ftgmac100Desc); } } s->tx_descriptor = addr; ftgmac100_update_irq(s); }
/** * smmu_find_ste - Return the stream table entry associated * to the sid * * @s: smmuv3 handle * @sid: stream ID * @ste: returned stream table entry * @event: handle to an event info * * Supports linear and 2-level stream table * Return 0 on success, -EINVAL otherwise */ static int smmu_find_ste(SMMUv3State *s, uint32_t sid, STE *ste, SMMUEventInfo *event) { dma_addr_t addr; int ret; trace_smmuv3_find_ste(sid, s->features, s->sid_split); /* Check SID range */ if (sid > (1 << SMMU_IDR1_SIDSIZE)) { event->type = SMMU_EVT_C_BAD_STREAMID; return -EINVAL; } if (s->features & SMMU_FEATURE_2LVL_STE) { int l1_ste_offset, l2_ste_offset, max_l2_ste, span; dma_addr_t strtab_base, l1ptr, l2ptr; STEDesc l1std; strtab_base = s->strtab_base & SMMU_BASE_ADDR_MASK; l1_ste_offset = sid >> s->sid_split; l2_ste_offset = sid & ((1 << s->sid_split) - 1); l1ptr = (dma_addr_t)(strtab_base + l1_ste_offset * sizeof(l1std)); /* TODO: guarantee 64-bit single-copy atomicity */ ret = dma_memory_read(&address_space_memory, l1ptr, (uint8_t *)&l1std, sizeof(l1std)); if (ret != MEMTX_OK) { qemu_log_mask(LOG_GUEST_ERROR, "Could not read L1PTR at 0X%"PRIx64"\n", l1ptr); event->type = SMMU_EVT_F_STE_FETCH; event->u.f_ste_fetch.addr = l1ptr; return -EINVAL; } span = L1STD_SPAN(&l1std); if (!span) { /* l2ptr is not valid */ qemu_log_mask(LOG_GUEST_ERROR, "invalid sid=%d (L1STD span=0)\n", sid); event->type = SMMU_EVT_C_BAD_STREAMID; return -EINVAL; } max_l2_ste = (1 << span) - 1; l2ptr = l1std_l2ptr(&l1std); trace_smmuv3_find_ste_2lvl(s->strtab_base, l1ptr, l1_ste_offset, l2ptr, l2_ste_offset, max_l2_ste); if (l2_ste_offset > max_l2_ste) { qemu_log_mask(LOG_GUEST_ERROR, "l2_ste_offset=%d > max_l2_ste=%d\n", l2_ste_offset, max_l2_ste); event->type = SMMU_EVT_C_BAD_STE; return -EINVAL; } addr = l2ptr + l2_ste_offset * sizeof(*ste); } else {
/* @ssid > 0 not supported yet */ static int smmu_get_cd(SMMUv3State *s, STE *ste, uint32_t ssid, CD *buf, SMMUEventInfo *event) { dma_addr_t addr = STE_CTXPTR(ste); int ret; trace_smmuv3_get_cd(addr); /* TODO: guarantee 64-bit single-copy atomicity */ ret = dma_memory_read(&address_space_memory, addr, (void *)buf, sizeof(*buf)); if (ret != MEMTX_OK) { qemu_log_mask(LOG_GUEST_ERROR, "Cannot fetch pte at address=0x%"PRIx64"\n", addr); event->type = SMMU_EVT_F_CD_FETCH; event->u.f_ste_fetch.addr = addr; return -EINVAL; } return 0; }
static inline MemTxResult queue_read(SMMUQueue *q, void *data) { dma_addr_t addr = Q_CONS_ENTRY(q); return dma_memory_read(&address_space_memory, addr, data, q->entry_size); }