diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2013-02-05 13:35:34 +0100 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2013-04-08 18:13:14 +0200 |
commit | 9944d320016914912133b348b6fbbb18c7417035 (patch) | |
tree | 833e579b5902d0b3eeb392d74d20433f29fdea70 /hw/mcf_uart.c | |
parent | 80b4ecc86dd5ccd779f96c8bd11feb031d327614 (diff) |
hw: move char devices to hw/char/, configure via default-configs/
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'hw/mcf_uart.c')
-rw-r--r-- | hw/mcf_uart.c | 307 |
1 files changed, 0 insertions, 307 deletions
diff --git a/hw/mcf_uart.c b/hw/mcf_uart.c deleted file mode 100644 index 6724b1b718..0000000000 --- a/hw/mcf_uart.c +++ /dev/null @@ -1,307 +0,0 @@ -/* - * ColdFire UART emulation. - * - * Copyright (c) 2007 CodeSourcery. - * - * This code is licensed under the GPL - */ -#include "hw/hw.h" -#include "hw/m68k/mcf.h" -#include "char/char.h" -#include "exec/address-spaces.h" - -typedef struct { - MemoryRegion iomem; - uint8_t mr[2]; - uint8_t sr; - uint8_t isr; - uint8_t imr; - uint8_t bg1; - uint8_t bg2; - uint8_t fifo[4]; - uint8_t tb; - int current_mr; - int fifo_len; - int tx_enabled; - int rx_enabled; - qemu_irq irq; - CharDriverState *chr; -} mcf_uart_state; - -/* UART Status Register bits. */ -#define MCF_UART_RxRDY 0x01 -#define MCF_UART_FFULL 0x02 -#define MCF_UART_TxRDY 0x04 -#define MCF_UART_TxEMP 0x08 -#define MCF_UART_OE 0x10 -#define MCF_UART_PE 0x20 -#define MCF_UART_FE 0x40 -#define MCF_UART_RB 0x80 - -/* Interrupt flags. */ -#define MCF_UART_TxINT 0x01 -#define MCF_UART_RxINT 0x02 -#define MCF_UART_DBINT 0x04 -#define MCF_UART_COSINT 0x80 - -/* UMR1 flags. */ -#define MCF_UART_BC0 0x01 -#define MCF_UART_BC1 0x02 -#define MCF_UART_PT 0x04 -#define MCF_UART_PM0 0x08 -#define MCF_UART_PM1 0x10 -#define MCF_UART_ERR 0x20 -#define MCF_UART_RxIRQ 0x40 -#define MCF_UART_RxRTS 0x80 - -static void mcf_uart_update(mcf_uart_state *s) -{ - s->isr &= ~(MCF_UART_TxINT | MCF_UART_RxINT); - if (s->sr & MCF_UART_TxRDY) - s->isr |= MCF_UART_TxINT; - if ((s->sr & ((s->mr[0] & MCF_UART_RxIRQ) - ? MCF_UART_FFULL : MCF_UART_RxRDY)) != 0) - s->isr |= MCF_UART_RxINT; - - qemu_set_irq(s->irq, (s->isr & s->imr) != 0); -} - -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; - } -} - -/* Update TxRDY flag and set data if present and enabled. */ -static void mcf_uart_do_tx(mcf_uart_state *s) -{ - if (s->tx_enabled && (s->sr & MCF_UART_TxEMP) == 0) { - if (s->chr) - qemu_chr_fe_write(s->chr, (unsigned char *)&s->tb, 1); - s->sr |= MCF_UART_TxEMP; - } - if (s->tx_enabled) { - s->sr |= MCF_UART_TxRDY; - } else { - s->sr &= ~MCF_UART_TxRDY; - } -} - -static void mcf_do_command(mcf_uart_state *s, uint8_t cmd) -{ - /* Misc command. */ - switch ((cmd >> 4) & 3) { - case 0: /* No-op. */ - break; - case 1: /* Reset mode register pointer. */ - s->current_mr = 0; - break; - case 2: /* Reset receiver. */ - s->rx_enabled = 0; - s->fifo_len = 0; - s->sr &= ~(MCF_UART_RxRDY | MCF_UART_FFULL); - break; - case 3: /* Reset transmitter. */ - s->tx_enabled = 0; - s->sr |= MCF_UART_TxEMP; - s->sr &= ~MCF_UART_TxRDY; - break; - case 4: /* Reset error status. */ - break; - case 5: /* Reset break-change interrupt. */ - s->isr &= ~MCF_UART_DBINT; - break; - case 6: /* Start break. */ - case 7: /* Stop break. */ - break; - } - - /* Transmitter command. */ - switch ((cmd >> 2) & 3) { - case 0: /* No-op. */ - break; - case 1: /* Enable. */ - s->tx_enabled = 1; - mcf_uart_do_tx(s); - break; - case 2: /* Disable. */ - s->tx_enabled = 0; - mcf_uart_do_tx(s); - break; - case 3: /* Reserved. */ - fprintf(stderr, "mcf_uart: Bad TX command\n"); - break; - } - - /* Receiver command. */ - switch (cmd & 3) { - case 0: /* No-op. */ - break; - case 1: /* Enable. */ - s->rx_enabled = 1; - break; - case 2: - s->rx_enabled = 0; - break; - case 3: /* Reserved. */ - fprintf(stderr, "mcf_uart: Bad RX command\n"); - break; - } -} - -void mcf_uart_write(void *opaque, hwaddr addr, - uint64_t val, unsigned size) -{ - mcf_uart_state *s = (mcf_uart_state *)opaque; - switch (addr & 0x3f) { - case 0x00: - s->mr[s->current_mr] = val; - s->current_mr = 1; - break; - case 0x04: - /* CSR is ignored. */ - break; - case 0x08: /* Command Register. */ - mcf_do_command(s, val); - break; - case 0x0c: /* Transmit Buffer. */ - s->sr &= ~MCF_UART_TxEMP; - s->tb = val; - mcf_uart_do_tx(s); - break; - case 0x10: - /* ACR is ignored. */ - break; - case 0x14: - s->imr = val; - break; - default: - break; - } - mcf_uart_update(s); -} - -static void mcf_uart_reset(mcf_uart_state *s) -{ - s->fifo_len = 0; - s->mr[0] = 0; - s->mr[1] = 0; - s->sr = MCF_UART_TxEMP; - s->tx_enabled = 0; - s->rx_enabled = 0; - s->isr = 0; - s->imr = 0; -} - -static void mcf_uart_push_byte(mcf_uart_state *s, uint8_t data) -{ - /* Break events overwrite the last byte if the fifo is full. */ - if (s->fifo_len == 4) - s->fifo_len--; - - s->fifo[s->fifo_len] = data; - s->fifo_len++; - s->sr |= MCF_UART_RxRDY; - if (s->fifo_len == 4) - s->sr |= MCF_UART_FFULL; - - mcf_uart_update(s); -} - -static void mcf_uart_event(void *opaque, int event) -{ - mcf_uart_state *s = (mcf_uart_state *)opaque; - - switch (event) { - case CHR_EVENT_BREAK: - s->isr |= MCF_UART_DBINT; - mcf_uart_push_byte(s, 0); - break; - default: - break; - } -} - -static int mcf_uart_can_receive(void *opaque) -{ - mcf_uart_state *s = (mcf_uart_state *)opaque; - - return s->rx_enabled && (s->sr & MCF_UART_FFULL) == 0; -} - -static void mcf_uart_receive(void *opaque, const uint8_t *buf, int size) -{ - mcf_uart_state *s = (mcf_uart_state *)opaque; - - mcf_uart_push_byte(s, buf[0]); -} - -void *mcf_uart_init(qemu_irq irq, CharDriverState *chr) -{ - mcf_uart_state *s; - - s = g_malloc0(sizeof(mcf_uart_state)); - s->chr = chr; - s->irq = irq; - if (chr) { - qemu_chr_fe_claim_no_fail(chr); - qemu_chr_add_handlers(chr, mcf_uart_can_receive, mcf_uart_receive, - mcf_uart_event, s); - } - mcf_uart_reset(s); - return s; -} - -static const MemoryRegionOps mcf_uart_ops = { - .read = mcf_uart_read, - .write = mcf_uart_write, - .endianness = DEVICE_NATIVE_ENDIAN, -}; - -void mcf_uart_mm_init(MemoryRegion *sysmem, - hwaddr base, - qemu_irq irq, - CharDriverState *chr) -{ - mcf_uart_state *s; - - s = mcf_uart_init(irq, chr); - memory_region_init_io(&s->iomem, &mcf_uart_ops, s, "uart", 0x40); - memory_region_add_subregion(sysmem, base, &s->iomem); -} |