static void pit_timer_hit(void *opaque) { XilinxPIT *s = XILINX_IO_MODULE_PIT(opaque); qemu_irq_pulse(s->irq); /* hit_out to make another pit move its counter in pre-scalar mode */ qemu_irq_pulse(s->hit_out); }
static inline void eth_pulse_irq(struct xlx_ethlite *s) { /* Only the first gie reg is active. */ if (s->regs[R_TX_GIE0] & GIE_GIE) { qemu_irq_pulse(s->irq); } }
static void ac97_write(void *opaque, target_phys_addr_t addr, uint64_t value, unsigned size) { MilkymistAC97State *s = opaque; trace_milkymist_ac97_memory_write(addr, value); addr >>= 2; switch (addr) { case R_AC97_CTRL: /* always raise an IRQ according to the direction */ if (value & AC97_CTRL_RQEN) { if (value & AC97_CTRL_WRITE) { trace_milkymist_ac97_pulse_irq_crrequest(); qemu_irq_pulse(s->crrequest_irq); } else { trace_milkymist_ac97_pulse_irq_crreply(); qemu_irq_pulse(s->crreply_irq); } } /* RQEN is self clearing */ s->regs[addr] = value & ~AC97_CTRL_RQEN; break; case R_D_CTRL: case R_U_CTRL: s->regs[addr] = value; update_voices(s); break; case R_AC97_ADDR: case R_AC97_DATAOUT: case R_AC97_DATAIN: case R_D_ADDR: case R_D_REMAINING: case R_U_ADDR: case R_U_REMAINING: s->regs[addr] = value; break; default: error_report("milkymist_ac97: write access to unknown register 0x" TARGET_FMT_plx, addr); break; } }
void isr_notify(NVMEState *n, NVMEIOCQueue *cq) { if (cq->irq_enabled) { if (msix_enabled(&(n->dev))) { msix_notify(&(n->dev), cq->vector); } else { qemu_irq_pulse(n->dev.irq[0]); } } }
static void nvme_isr_notify(NvmeCtrl *n, NvmeCQueue *cq) { if (cq->irq_enabled) { if (msix_enabled(&(n->parent_obj))) { msix_notify(&(n->parent_obj), cq->vector); } else { qemu_irq_pulse(n->parent_obj.irq[0]); } } }
static void grlib_apbuart_receive(void *opaque, const uint8_t *buf, int size) { UART *uart = opaque; uart->receive = *buf; uart->status |= UART_DATA_READY; if (uart->control & UART_RECEIVE_INTERRUPT) { qemu_irq_pulse(uart->irq); } }
static void uart_tx_pw(DepRegisterInfo *reg, uint64_t value) { XilinxUART *s = XILINX_IO_MODULE_UART(reg->opaque); if (s->cfg.use_tx) { unsigned char ch = value; qemu_chr_fe_write(&s->chr, &ch, 1); if (s->cfg.tx_interrupt) { qemu_irq_pulse(s->irq_tx); } } }
static void stm32f2xx_timer_interrupt(void *opaque) { STM32F2XXTimerState *s = opaque; DB_PRINT("Interrupt\n"); if (s->tim_dier & TIM_DIER_UIE && s->tim_cr1 & TIM_CR1_CEN) { s->tim_sr |= 1; qemu_irq_pulse(s->irq); stm32f2xx_timer_set_alarm(s, s->hit_time); } }
static void timer1_hit(void *opaque) { MilkymistSysctlState *s = opaque; if (!(s->regs[R_TIMER1_CONTROL] & CTRL_AUTORESTART)) { s->regs[R_TIMER1_CONTROL] &= ~CTRL_ENABLE; trace_milkymist_sysctl_stop_timer1(); ptimer_stop(s->ptimer1); } trace_milkymist_sysctl_pulse_irq_timer1(); qemu_irq_pulse(s->timer1_irq); }
static void uart_rx(void *opaque, const uint8_t *buf, int size) { XilinxUART *s = opaque; if (!s->cfg.use_rx) { return; } if (s->regs[R_IOM_UART_STATUS] & IOM_UART_STATUS_RX_VALID) { s->regs[R_IOM_UART_STATUS] |= IOM_UART_STATUS_OVERRUN; if (s->cfg.err_interrupt) { qemu_irq_pulse(s->irq_err); } return; } s->regs[R_IOM_UART_RX] = *buf; s->regs[R_IOM_UART_STATUS] |= IOM_UART_STATUS_RX_VALID; if (s->cfg.rx_interrupt) { qemu_irq_pulse(s->irq_rx); } }
static void grlib_apbuart_receive(void *opaque, const uint8_t *buf, int size) { UART *uart = opaque; if (uart->control & UART_RECEIVE_ENABLE) { uart_add_to_fifo(uart, buf, size); uart->status |= UART_DATA_READY; if (uart->control & UART_RECEIVE_INTERRUPT) { qemu_irq_pulse(uart->irq); } } }
static inline void omap_gp_timer_intr(struct omap_gp_timer_s *timer, int it) { if (timer->it_ena & it) { if (!timer->status) qemu_irq_raise(timer->irq); timer->status |= it; /* Or are the status bits set even when masked? * i.e. is masking applied before or after the status register? */ } if (timer->wu_ena & it) qemu_irq_pulse(timer->wkup); }
static void grlib_apbuart_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { UART *uart = opaque; unsigned char c = 0; addr &= 0xff; /* Unit registers */ switch (addr) { case DATA_OFFSET: case DATA_OFFSET + 3: /* When only one byte write */ /* Transmit when character device available and transmitter enabled */ if (qemu_chr_fe_get_driver(&uart->chr) && (uart->control & UART_TRANSMIT_ENABLE)) { c = value & 0xFF; /* XXX this blocks entire thread. Rewrite to use * qemu_chr_fe_write and background I/O callbacks */ qemu_chr_fe_write_all(&uart->chr, &c, 1); /* Generate interrupt */ if (uart->control & UART_TRANSMIT_INTERRUPT) { qemu_irq_pulse(uart->irq); } } return; case STATUS_OFFSET: /* Read Only */ return; case CONTROL_OFFSET: uart->control = value; return; case SCALER_OFFSET: /* Not supported */ return; default: break; } trace_grlib_apbuart_writel_unknown(addr, value); }
static void grlib_gptimer_hit(void *opaque) { GPTimer *timer = opaque; assert(timer != NULL); trace_grlib_gptimer_hit(timer->id); /* Timer expired */ if (timer->config & GPTIMER_INT_ENABLE) { /* Set the pending bit (only unset by write in the config register) */ timer->config |= GPTIMER_INT_PENDING; qemu_irq_pulse(timer->irq); } if (timer->config & GPTIMER_RESTART) { grlib_gptimer_restart(timer); } }
static void ac97_in_cb(void *opaque, int avail_b) { MilkymistAC97State *s = opaque; uint8_t buf[4096]; uint32_t remaining = s->regs[R_U_REMAINING]; int temp = audio_MIN(remaining, avail_b); uint32_t addr = s->regs[R_U_ADDR]; int transferred = 0; trace_milkymist_ac97_in_cb(avail_b, remaining); /* prevent from raising an IRQ */ if (temp == 0) { return; } while (temp) { int acquired, to_copy; to_copy = audio_MIN(temp, sizeof(buf)); acquired = AUD_read(s->voice_in, buf, to_copy); if (!acquired) { break; } cpu_physical_memory_write(addr, buf, acquired); temp -= acquired; addr += acquired; transferred += acquired; } trace_milkymist_ac97_in_cb_transferred(transferred); s->regs[R_U_ADDR] = addr; s->regs[R_U_REMAINING] -= transferred; if ((s->regs[R_U_CTRL] & CTRL_EN) && (s->regs[R_U_REMAINING] == 0)) { trace_milkymist_ac97_pulse_irq_dmaw(); qemu_irq_pulse(s->dmaw_irq); } }
static void gptm_tick(void *opaque) { gptm_state **p = (gptm_state **)opaque; gptm_state *s; int n; s = *p; n = p - s->opaque; if (s->config == 0) { s->state |= 1; if ((s->control & 0x20)) { /* Output trigger. */ qemu_irq_pulse(s->trigger); } if (s->mode[0] & 1) { /* One-shot. */ s->control &= ~1; } else { /* Periodic. */ gptm_reload(s, 0, 0); } } else if (s->config == 1) { /* RTC. */ uint32_t match; s->rtc++; match = s->match[0] | (s->match[1] << 16); if (s->rtc > match) s->rtc = 0; if (s->rtc == 0) { s->state |= 8; } gptm_reload(s, 0, 0); } else if (s->mode[n] == 0xa) { /* PWM mode. Not implemented. */ } else { qemu_log_mask(LOG_UNIMP, "GPTM: 16-bit timer mode unimplemented: 0x%x\n", s->mode[n]); } gptm_update_irq(s); }
static void stm32f2xx_timer_interrupt(void *opaque) { STM32F2XXTimerState *s = opaque; DB_PRINT("Interrupt\n"); if (s->tim_dier & TIM_DIER_UIE && s->tim_cr1 & TIM_CR1_CEN) { s->tim_sr |= 1; qemu_irq_pulse(s->irq); stm32f2xx_timer_set_alarm(s, s->hit_time); } if (s->tim_ccmr1 & (TIM_CCMR1_OC2M2 | TIM_CCMR1_OC2M1) && !(s->tim_ccmr1 & TIM_CCMR1_OC2M0) && s->tim_ccmr1 & TIM_CCMR1_OC2PE && s->tim_ccer & TIM_CCER_CC2E) { /* PWM 2 - Mode 1 */ DB_PRINT("PWM2 Duty Cycle: %d%%\n", s->tim_ccr2 / (100 * (s->tim_psc + 1))); } }
/** * smmuv3_trigger_irq - pulse @irq if enabled and update * GERROR register in case of GERROR interrupt * * @irq: irq type * @gerror_mask: mask of gerrors to toggle (relevant if @irq is GERROR) */ static void smmuv3_trigger_irq(SMMUv3State *s, SMMUIrq irq, uint32_t gerror_mask) { bool pulse = false; switch (irq) { case SMMU_IRQ_EVTQ: pulse = smmuv3_eventq_irq_enabled(s); break; case SMMU_IRQ_PRIQ: qemu_log_mask(LOG_UNIMP, "PRI not yet supported\n"); break; case SMMU_IRQ_CMD_SYNC: pulse = true; break; case SMMU_IRQ_GERROR: { uint32_t pending = s->gerror ^ s->gerrorn; uint32_t new_gerrors = ~pending & gerror_mask; if (!new_gerrors) { /* only toggle non pending errors */ return; } s->gerror ^= new_gerrors; trace_smmuv3_write_gerror(new_gerrors, s->gerror); pulse = smmuv3_gerror_irq_enabled(s); break; } } if (pulse) { trace_smmuv3_trigger_irq(irq); qemu_irq_pulse(s->irq[irq]); } }
static ssize_t spapr_vlan_receive(NetClientState *nc, const uint8_t *buf, size_t size) { VIOsPAPRDevice *sdev = DO_UPCAST(NICState, nc, nc)->opaque; VIOsPAPRVLANDevice *dev = (VIOsPAPRVLANDevice *)sdev; vlan_bd_t rxq_bd = vio_ldq(sdev, dev->buf_list + VLAN_RXQ_BD_OFF); vlan_bd_t bd; int buf_ptr = dev->use_buf_ptr; uint64_t handle; uint8_t control; dprintf("spapr_vlan_receive() [%s] rx_bufs=%d\n", sdev->qdev.id, dev->rx_bufs); if (!dev->isopen) { return -1; } if (!dev->rx_bufs) { return -1; } do { buf_ptr += 8; if (buf_ptr >= SPAPR_TCE_PAGE_SIZE) { buf_ptr = VLAN_RX_BDS_OFF; } bd = vio_ldq(sdev, dev->buf_list + buf_ptr); dprintf("use_buf_ptr=%d bd=0x%016llx\n", buf_ptr, (unsigned long long)bd); } while ((!(bd & VLAN_BD_VALID) || (VLAN_BD_LEN(bd) < (size + 8))) && (buf_ptr != dev->use_buf_ptr)); if (!(bd & VLAN_BD_VALID) || (VLAN_BD_LEN(bd) < (size + 8))) { /* Failed to find a suitable buffer */ return -1; } /* Remove the buffer from the pool */ dev->rx_bufs--; dev->use_buf_ptr = buf_ptr; vio_stq(sdev, dev->buf_list + dev->use_buf_ptr, 0); dprintf("Found buffer: ptr=%d num=%d\n", dev->use_buf_ptr, dev->rx_bufs); /* Transfer the packet data */ if (spapr_vio_dma_write(sdev, VLAN_BD_ADDR(bd) + 8, buf, size) < 0) { return -1; } dprintf("spapr_vlan_receive: DMA write completed\n"); /* Update the receive queue */ control = VLAN_RXQC_TOGGLE | VLAN_RXQC_VALID; if (rxq_bd & VLAN_BD_TOGGLE) { control ^= VLAN_RXQC_TOGGLE; } handle = vio_ldq(sdev, VLAN_BD_ADDR(bd)); vio_stq(sdev, VLAN_BD_ADDR(rxq_bd) + dev->rxq_ptr + 8, handle); vio_stl(sdev, VLAN_BD_ADDR(rxq_bd) + dev->rxq_ptr + 4, size); vio_sth(sdev, VLAN_BD_ADDR(rxq_bd) + dev->rxq_ptr + 2, 8); vio_stb(sdev, VLAN_BD_ADDR(rxq_bd) + dev->rxq_ptr, control); dprintf("wrote rxq entry (ptr=0x%llx): 0x%016llx 0x%016llx\n", (unsigned long long)dev->rxq_ptr, (unsigned long long)vio_ldq(sdev, VLAN_BD_ADDR(rxq_bd) + dev->rxq_ptr), (unsigned long long)vio_ldq(sdev, VLAN_BD_ADDR(rxq_bd) + dev->rxq_ptr + 8)); dev->rxq_ptr += 16; if (dev->rxq_ptr >= VLAN_BD_LEN(rxq_bd)) { dev->rxq_ptr = 0; vio_stq(sdev, dev->buf_list + VLAN_RXQ_BD_OFF, rxq_bd ^ VLAN_BD_TOGGLE); } if (sdev->signal_state & 1) { qemu_irq_pulse(spapr_vio_qirq(sdev)); } return size; }
static ssize_t spapr_vlan_receive(NetClientState *nc, const uint8_t *buf, size_t size) { VIOsPAPRVLANDevice *dev = qemu_get_nic_opaque(nc); VIOsPAPRDevice *sdev = VIO_SPAPR_DEVICE(dev); vlan_bd_t rxq_bd = vio_ldq(sdev, dev->buf_list + VLAN_RXQ_BD_OFF); vlan_bd_t bd; uint64_t handle; uint8_t control; trace_spapr_vlan_receive(sdev->qdev.id, dev->rx_bufs); if (!dev->isopen) { return -1; } if (!dev->rx_bufs) { spapr_vlan_record_dropped_rx_frame(dev); return 0; } if (dev->compat_flags & SPAPRVLAN_FLAG_RX_BUF_POOLS) { bd = spapr_vlan_get_rx_bd_from_pool(dev, size); } else { bd = spapr_vlan_get_rx_bd_from_page(dev, size); } if (!bd) { spapr_vlan_record_dropped_rx_frame(dev); return 0; } dev->rx_bufs--; /* Transfer the packet data */ if (spapr_vio_dma_write(sdev, VLAN_BD_ADDR(bd) + 8, buf, size) < 0) { return -1; } trace_spapr_vlan_receive_dma_completed(); /* Update the receive queue */ control = VLAN_RXQC_TOGGLE | VLAN_RXQC_VALID; if (rxq_bd & VLAN_BD_TOGGLE) { control ^= VLAN_RXQC_TOGGLE; } handle = vio_ldq(sdev, VLAN_BD_ADDR(bd)); vio_stq(sdev, VLAN_BD_ADDR(rxq_bd) + dev->rxq_ptr + 8, handle); vio_stl(sdev, VLAN_BD_ADDR(rxq_bd) + dev->rxq_ptr + 4, size); vio_sth(sdev, VLAN_BD_ADDR(rxq_bd) + dev->rxq_ptr + 2, 8); vio_stb(sdev, VLAN_BD_ADDR(rxq_bd) + dev->rxq_ptr, control); trace_spapr_vlan_receive_wrote(dev->rxq_ptr, vio_ldq(sdev, VLAN_BD_ADDR(rxq_bd) + dev->rxq_ptr), vio_ldq(sdev, VLAN_BD_ADDR(rxq_bd) + dev->rxq_ptr + 8)); dev->rxq_ptr += 16; if (dev->rxq_ptr >= VLAN_BD_LEN(rxq_bd)) { dev->rxq_ptr = 0; vio_stq(sdev, dev->buf_list + VLAN_RXQ_BD_OFF, rxq_bd ^ VLAN_BD_TOGGLE); } if (sdev->signal_state & 1) { qemu_irq_pulse(spapr_vio_qirq(sdev)); } return size; }
static void gicv2m_set_irq(void *opaque, int irq) { ARMGICv2mState *s = (ARMGICv2mState *)opaque; qemu_irq_pulse(s->spi[irq]); }