static uint64_t imx_serial_read(void *opaque, target_phys_addr_t offset, unsigned size) { IMXSerialState *s = (IMXSerialState *)opaque; uint32_t c; DPRINTF("read(offset=%x)\n", offset >> 2); switch (offset >> 2) { case 0x0: /* URXD */ c = s->readbuff; if (!(s->uts1 & UTS1_RXEMPTY)) { /* Character is valid */ c |= URXD_CHARRDY; s->usr1 &= ~USR1_RRDY; s->usr2 &= ~USR2_RDR; s->uts1 |= UTS1_RXEMPTY; imx_update(s); qemu_chr_accept_input(s->chr); } return c; case 0x20: /* UCR1 */ return s->ucr1; case 0x21: /* UCR2 */ return s->ucr2; case 0x25: /* USR1 */ return s->usr1; case 0x26: /* USR2 */ return s->usr2; case 0x2A: /* BRM Modulator */ return s->ubmr; case 0x2B: /* Baud Rate Count */ return s->ubrc; case 0x2d: /* Test register */ return s->uts1; case 0x24: /* UFCR */ return s->ufcr; case 0x2c: return s->onems; case 0x22: /* UCR3 */ return s->ucr3; case 0x23: /* UCR4 */ case 0x29: /* BRM Incremental */ return 0x0; /* TODO */ default: IPRINTF("imx_serial_read: bad offset: 0x%x\n", (int)offset); return 0; } }
static void uart_read_rx_fifo(UartState *s, uint32_t *c) { if ((s->r[R_CR] & UART_CR_RX_DIS) || !(s->r[R_CR] & UART_CR_RX_EN)) { return; } s->r[R_SR] &= ~UART_SR_INTR_RFUL; if (s->rx_count) { uint32_t rx_rpos = (RX_FIFO_SIZE + s->rx_wpos - s->rx_count) % RX_FIFO_SIZE; *c = s->r_fifo[rx_rpos]; s->rx_count--; if (!s->rx_count) { s->r[R_SR] |= UART_SR_INTR_REMPTY; } qemu_chr_accept_input(s->chr); } else { *c = 0; s->r[R_SR] |= UART_SR_INTR_REMPTY; } if (s->rx_count < s->r[R_RTRIG]) { s->r[R_SR] &= ~UART_SR_INTR_RTRIG; } uart_update_status(s); }
static uint64_t uart_read(void *opaque, hwaddr addr, unsigned size) { LM32UartState *s = opaque; uint32_t r = 0; addr >>= 2; switch (addr) { case R_RXTX: r = s->regs[R_RXTX]; s->regs[R_LSR] &= ~LSR_DR; uart_update_irq(s); qemu_chr_accept_input(s->chr); break; case R_IIR: case R_LSR: case R_MSR: r = s->regs[addr]; break; case R_IER: case R_LCR: case R_MCR: case R_DIV: error_report("lm32_uart: read access to write only register 0x" TARGET_FMT_plx, addr << 2); break; default: error_report("lm32_uart: read access to unknown register 0x" TARGET_FMT_plx, addr << 2); break; } trace_lm32_uart_memory_read(addr << 2, r); return r; }
static uint64_t uart_read(void *opaque, hwaddr addr, unsigned int size) { struct xlx_uartlite *s = opaque; uint32_t r = 0; addr >>= 2; switch (addr) { case R_RX: r = s->rx_fifo[(s->rx_fifo_pos - s->rx_fifo_len) & 7]; if (s->rx_fifo_len) s->rx_fifo_len--; uart_update_status(s); uart_update_irq(s); qemu_chr_accept_input(s->chr); break; default: if (addr < ARRAY_SIZE(s->regs)) r = s->regs[addr]; DUART(qemu_log("%s addr=%x v=%x\n", __func__, addr, r)); break; } return r; }
static uint32_t slavio_serial_mem_readb(void *opaque, target_phys_addr_t addr) { SerialState *serial = opaque; ChannelState *s; uint32_t saddr; uint32_t ret; int channel; saddr = (addr & 3) >> 1; channel = (addr & SERIAL_MAXADDR) >> 2; s = &serial->chn[channel]; switch (saddr) { case SERIAL_CTRL: SER_DPRINTF("Read channel %c, reg[%d] = %2.2x\n", CHN_C(s), s->reg, s->rregs[s->reg]); ret = s->rregs[s->reg]; s->reg = 0; return ret; case SERIAL_DATA: s->rregs[R_STATUS] &= ~STATUS_RXAV; clr_rxint(s); if (s->type == kbd || s->type == mouse) ret = get_queue(s); else ret = s->rx; SER_DPRINTF("Read channel %c, ch %d\n", CHN_C(s), ret); if (s->chr) qemu_chr_accept_input(s->chr); return ret; default: break; } return 0; }
static uint64_t pl011_read(void *opaque, hwaddr offset, unsigned size) { PL011State *s = (PL011State *)opaque; uint32_t c; if (offset >= 0xfe0 && offset < 0x1000) { return s->id[(offset - 0xfe0) >> 2]; } switch (offset >> 2) { case 0: /* UARTDR */ s->flags &= ~PL011_FLAG_RXFF; c = s->read_fifo[s->read_pos]; if (s->read_count > 0) { s->read_count--; if (++s->read_pos == 16) s->read_pos = 0; } if (s->read_count == 0) { s->flags |= PL011_FLAG_RXFE; } if (s->read_count == s->read_trigger - 1) s->int_level &= ~ PL011_INT_RX; s->rsr = c >> 8; pl011_update(s); if (s->chr) { qemu_chr_accept_input(s->chr); } return c; case 1: /* UARTRSR */ return s->rsr; case 6: /* UARTFR */ return s->flags; case 8: /* UARTILPR */ return s->ilpr; case 9: /* UARTIBRD */ return s->ibrd; case 10: /* UARTFBRD */ return s->fbrd; case 11: /* UARTLCR_H */ return s->lcr; case 12: /* UARTCR */ return s->cr; case 13: /* UARTIFLS */ return s->ifl; case 14: /* UARTIMSC */ return s->int_enabled; case 15: /* UARTRIS */ return s->int_level; case 16: /* UARTMIS */ return s->int_level & s->int_enabled; case 18: /* UARTDMACR */ return s->dmacr; default: qemu_log_mask(LOG_GUEST_ERROR, "pl011_read: Bad offset %x\n", (int)offset); return 0; } }
static void uart_rx_reset(UartState *s) { s->rx_wpos = 0; s->rx_count = 0; if (s->chr) { qemu_chr_accept_input(s->chr); } }
static void uart_rx_reset(UartState *s) { s->rx_wpos = 0; s->rx_count = 0; qemu_chr_accept_input(s->chr); s->r[R_SR] |= UART_SR_INTR_REMPTY; s->r[R_SR] &= ~UART_SR_INTR_RFUL; }
static uint32_t pl011_read(void *opaque, target_phys_addr_t offset) { pl011_state *s = (pl011_state *)opaque; uint32_t c; if (offset >= 0xfe0 && offset < 0x1000) { return s->id[(offset - 0xfe0) >> 2]; } switch (offset >> 2) { case 0: /* UARTDR */ s->flags &= ~PL011_FLAG_RXFF; c = s->read_fifo[s->read_pos]; if (s->read_count > 0) { s->read_count--; if (++s->read_pos == 16) s->read_pos = 0; } if (s->read_count == 0) { s->flags |= PL011_FLAG_RXFE; } if (s->read_count == s->read_trigger - 1) s->int_level &= ~ PL011_INT_RX; pl011_update(s); qemu_chr_accept_input(s->chr); return c; case 1: /* UARTCR */ return 0; case 6: /* UARTFR */ return s->flags; case 8: /* UARTILPR */ return s->ilpr; case 9: /* UARTIBRD */ return s->ibrd; case 10: /* UARTFBRD */ return s->fbrd; case 11: /* UARTLCR_H */ return s->lcr; case 12: /* UARTCR */ return s->cr; case 13: /* UARTIFLS */ return s->ifl; case 14: /* UARTIMSC */ return s->int_enabled; case 15: /* UARTRIS */ return s->int_level; case 16: /* UARTMIS */ return s->int_level & s->int_enabled; case 18: /* UARTDMACR */ return s->dmacr; default: hw_error("pl011_read: Bad offset %x\n", (int)offset); return 0; } }
static void uart_read_rx_fifo(UartState *s, uint32_t *c) { if ((s->r[R_CR] & UART_CR_RX_DIS) || !(s->r[R_CR] & UART_CR_RX_EN)) { return; } if (s->rx_count) { uint32_t rx_rpos = (RX_FIFO_SIZE + s->rx_wpos - s->rx_count) % RX_FIFO_SIZE; *c = s->rx_fifo[rx_rpos]; s->rx_count--; qemu_chr_accept_input(s->chr); } else { *c = 0; } uart_update_status(s); }
uint64_t mcf_uart_read(void *opaque, hwaddr addr, unsigned size) { mcf_uart_state *s = (mcf_uart_state *)opaque; switch (addr & 0x3f) { case 0x00: return s->mr[s->current_mr]; case 0x04: return s->sr; case 0x0c: { uint8_t val; int i; if (s->fifo_len == 0) return 0; val = s->fifo[0]; s->fifo_len--; for (i = 0; i < s->fifo_len; i++) s->fifo[i] = s->fifo[i + 1]; s->sr &= ~MCF_UART_FFULL; if (s->fifo_len == 0) s->sr &= ~MCF_UART_RxRDY; mcf_uart_update(s); qemu_chr_accept_input(s->chr); return val; } case 0x10: /* TODO: Implement IPCR. */ return 0; case 0x14: return s->isr; case 0x18: return s->bg1; case 0x1c: return s->bg2; default: return 0; } }
static void uart_write(void *opaque, hwaddr addr, uint64_t value, unsigned size) { MilkymistUartState *s = opaque; unsigned char ch = value; trace_milkymist_uart_memory_write(addr, value); addr >>= 2; switch (addr) { case R_RXTX: if (s->chr) { qemu_chr_fe_write_all(s->chr, &ch, 1); } s->regs[R_STAT] |= STAT_TX_EVT; break; case R_DIV: case R_CTRL: case R_DBG: s->regs[addr] = value; break; case R_STAT: /* write one to clear bits */ s->regs[addr] &= ~(value & (STAT_RX_EVT | STAT_TX_EVT)); qemu_chr_accept_input(s->chr); break; default: error_report("milkymist_uart: write access to unknown register 0x" TARGET_FMT_plx, addr << 2); break; } uart_update_irq(s); }
static void imx_serial_write(void *opaque, target_phys_addr_t offset, uint64_t value, unsigned size) { IMXSerialState *s = (IMXSerialState *)opaque; unsigned char ch; DPRINTF("write(offset=%x, value = %x) to %s\n", offset >> 2, (unsigned int)value, s->chr ? s->chr->label : "NODEV"); switch (offset >> 2) { case 0x10: /* UTXD */ ch = value; if (s->ucr2 & UCR2_TXEN) { if (s->chr) { qemu_chr_fe_write(s->chr, &ch, 1); } s->usr1 &= ~USR1_TRDY; imx_update(s); s->usr1 |= USR1_TRDY; imx_update(s); } break; case 0x20: /* UCR1 */ s->ucr1 = value & 0xffff; DPRINTF("write(ucr1=%x)\n", (unsigned int)value); imx_update(s); break; case 0x21: /* UCR2 */ /* * Only a few bits in control register 2 are implemented as yet. * If it's intended to use a real serial device as a back-end, this * register will have to be implemented more fully. */ if (!(value & UCR2_SRST)) { imx_serial_reset(s); imx_update(s); value |= UCR2_SRST; } if (value & UCR2_RXEN) { if (!(s->ucr2 & UCR2_RXEN)) { qemu_chr_accept_input(s->chr); } } s->ucr2 = value & 0xffff; break; case 0x25: /* USR1 */ value &= USR1_AWAKE | USR1_AIRINT | USR1_DTRD | USR1_AGTIM | USR1_FRAMERR | USR1_ESCF | USR1_RTSD | USR1_PARTYER; s->usr1 &= ~value; break; case 0x26: /* USR2 */ /* * Writing 1 to some bits clears them; all other * values are ignored */ value &= USR2_ADET | USR2_DTRF | USR2_IDLE | USR2_ACST | USR2_RIDELT | USR2_IRINT | USR2_WAKE | USR2_DCDDELT | USR2_RTSF | USR2_BRCD | USR2_ORE; s->usr2 &= ~value; break; /* * Linux expects to see what it writes to these registers * We don't currently alter the baud rate */ case 0x29: /* UBIR */ s->ubrc = value & 0xffff; break; case 0x2a: /* UBMR */ s->ubmr = value & 0xffff; break; case 0x2c: /* One ms reg */ s->onems = value & 0xffff; break; case 0x24: /* FIFO control register */ s->ufcr = value & 0xffff; break; case 0x22: /* UCR3 */ s->ucr3 = value & 0xffff; break; case 0x2d: /* UTS1 */ case 0x23: /* UCR4 */ IPRINTF("Unimplemented Register %x written to\n", offset >> 2); /* TODO */ break; default: IPRINTF("imx_serial_write: Bad offset 0x%x\n", (int)offset); } }
static uint64_t imx_serial_read(void *opaque, hwaddr offset, unsigned size) { IMXSerialState *s = (IMXSerialState *)opaque; uint32_t c; DPRINTF("read(offset=0x%" HWADDR_PRIx ")\n", offset); switch (offset >> 2) { case 0x0: /* URXD */ c = s->readbuff; if (!(s->uts1 & UTS1_RXEMPTY)) { /* Character is valid */ c |= URXD_CHARRDY; s->usr1 &= ~USR1_RRDY; s->usr2 &= ~USR2_RDR; s->uts1 |= UTS1_RXEMPTY; imx_update(s); if (s->chr) { qemu_chr_accept_input(s->chr); } } return c; case 0x20: /* UCR1 */ return s->ucr1; case 0x21: /* UCR2 */ return s->ucr2; case 0x25: /* USR1 */ return s->usr1; case 0x26: /* USR2 */ return s->usr2; case 0x2A: /* BRM Modulator */ return s->ubmr; case 0x2B: /* Baud Rate Count */ return s->ubrc; case 0x2d: /* Test register */ return s->uts1; case 0x24: /* UFCR */ return s->ufcr; case 0x2c: return s->onems; case 0x22: /* UCR3 */ return s->ucr3; case 0x23: /* UCR4 */ case 0x29: /* BRM Incremental */ return 0x0; /* TODO */ default: qemu_log_mask(LOG_GUEST_ERROR, "[%s]%s: Bad register at offset 0x%" HWADDR_PRIx "\n", TYPE_IMX_SERIAL, __func__, offset); return 0; } }
static uint64_t bcm2835_aux_read(void *opaque, hwaddr offset, unsigned size) { BCM2835AuxState *s = (BCM2835AuxState *)opaque; uint32_t c, res; switch (offset >> 2) { case 1: /* AUXENB */ return 1; /* mini UART enabled */ case 16: /* AUX_MU_IO_REG */ c = s->read_fifo[s->read_pos]; if (s->read_count > 0) { s->read_count--; if (++s->read_pos == 8) { s->read_pos = 0; } } if (s->chr) { qemu_chr_accept_input(s->chr); } bcm2835_aux_update(s); return c; case 17: /* AUX_MU_IIR_REG */ res = 0; if (s->rx_int_enable) { res |= 0x2; } if (s->tx_int_enable) { res |= 0x1; } return res; case 18: /* AUX_MU_IER_REG */ res = 0xc0; if (s->tx_int_enable) { res |= 0x1; } else if (s->rx_int_enable && s->read_count != 0) { res |= 0x2; } return res; case 21: /* AUX_MU_LSR_REG */ res = 0x60; /* tx idle, empty */ if (s->read_count != 0) { res |= 0x1; } return res; case 25: /* AUX_MU_STAT_REG */ res = 0x302; /* space in the output buffer, empty tx fifo */ if (s->read_count > 0) { res |= 0x1; /* data in input buffer */ assert(s->read_count < 8); res |= ((uint32_t)s->read_count) << 16; /* rx fifo fill level */ } return res; default: qemu_log_mask(LOG_GUEST_ERROR, "bcm2835_aux_read: Bad offset %x\n", (int)offset); return 0; } }