|
|
1.1 root 1: /*
2: * QEMU ETRAX System Emulator
3: *
4: * Copyright (c) 2007 Edgar E. Iglesias, Axis Communications AB.
5: *
6: * Permission is hereby granted, free of charge, to any person obtaining a copy
7: * of this software and associated documentation files (the "Software"), to deal
8: * in the Software without restriction, including without limitation the rights
9: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10: * copies of the Software, and to permit persons to whom the Software is
11: * furnished to do so, subject to the following conditions:
12: *
13: * The above copyright notice and this permission notice shall be included in
14: * all copies or substantial portions of the Software.
15: *
16: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19: * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21: * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22: * THE SOFTWARE.
23: */
24:
1.1.1.3 root 25: #include "sysbus.h"
1.1.1.2 root 26: #include "qemu-char.h"
1.1.1.8 ! root 27: #include "qemu-log.h"
1.1 root 28:
1.1.1.2 root 29: #define D(x)
1.1 root 30:
1.1.1.3 root 31: #define RW_TR_CTRL (0x00 / 4)
32: #define RW_TR_DMA_EN (0x04 / 4)
33: #define RW_REC_CTRL (0x08 / 4)
34: #define RW_DOUT (0x1c / 4)
35: #define RS_STAT_DIN (0x20 / 4)
36: #define R_STAT_DIN (0x24 / 4)
37: #define RW_INTR_MASK (0x2c / 4)
38: #define RW_ACK_INTR (0x30 / 4)
39: #define R_INTR (0x34 / 4)
40: #define R_MASKED_INTR (0x38 / 4)
41: #define R_MAX (0x3c / 4)
1.1.1.2 root 42:
43: #define STAT_DAV 16
44: #define STAT_TR_IDLE 22
45: #define STAT_TR_RDY 24
46:
1.1.1.3 root 47: struct etrax_serial
1.1.1.2 root 48: {
1.1.1.3 root 49: SysBusDevice busdev;
1.1.1.8 ! root 50: MemoryRegion mmio;
1.1.1.3 root 51: CharDriverState *chr;
52: qemu_irq irq;
1.1.1.2 root 53:
1.1.1.3 root 54: int pending_tx;
1.1.1.2 root 55:
1.1.1.5 root 56: uint8_t rx_fifo[16];
57: unsigned int rx_fifo_pos;
58: unsigned int rx_fifo_len;
59:
1.1.1.3 root 60: /* Control registers. */
61: uint32_t regs[R_MAX];
62: };
1.1.1.2 root 63:
1.1.1.3 root 64: static void ser_update_irq(struct etrax_serial *s)
1.1 root 65: {
1.1.1.3 root 66:
1.1.1.5 root 67: if (s->rx_fifo_len) {
68: s->regs[R_INTR] |= 8;
69: } else {
70: s->regs[R_INTR] &= ~8;
71: }
72:
73: s->regs[R_MASKED_INTR] = s->regs[R_INTR] & s->regs[RW_INTR_MASK];
1.1.1.3 root 74: qemu_set_irq(s->irq, !!s->regs[R_MASKED_INTR]);
1.1 root 75: }
76:
1.1.1.8 ! root 77: static uint64_t
! 78: ser_read(void *opaque, target_phys_addr_t addr, unsigned int size)
1.1 root 79: {
1.1.1.3 root 80: struct etrax_serial *s = opaque;
81: D(CPUState *env = s->env);
82: uint32_t r = 0;
83:
84: addr >>= 2;
85: switch (addr)
86: {
87: case R_STAT_DIN:
1.1.1.5 root 88: r = s->rx_fifo[(s->rx_fifo_pos - s->rx_fifo_len) & 15];
89: if (s->rx_fifo_len) {
90: r |= 1 << STAT_DAV;
91: }
92: r |= 1 << STAT_TR_RDY;
93: r |= 1 << STAT_TR_IDLE;
1.1.1.3 root 94: break;
95: case RS_STAT_DIN:
1.1.1.5 root 96: r = s->rx_fifo[(s->rx_fifo_pos - s->rx_fifo_len) & 15];
97: if (s->rx_fifo_len) {
98: r |= 1 << STAT_DAV;
99: s->rx_fifo_len--;
100: }
101: r |= 1 << STAT_TR_RDY;
102: r |= 1 << STAT_TR_IDLE;
1.1.1.3 root 103: break;
104: default:
105: r = s->regs[addr];
1.1.1.8 ! root 106: D(qemu_log("%s " TARGET_FMT_plx "=%x\n", __func__, addr, r));
1.1.1.3 root 107: break;
108: }
109: return r;
1.1 root 110: }
111:
112: static void
1.1.1.8 ! root 113: ser_write(void *opaque, target_phys_addr_t addr,
! 114: uint64_t val64, unsigned int size)
1.1 root 115: {
1.1.1.3 root 116: struct etrax_serial *s = opaque;
1.1.1.8 ! root 117: uint32_t value = val64;
! 118: unsigned char ch = val64;
1.1.1.3 root 119: D(CPUState *env = s->env);
120:
1.1.1.8 ! root 121: D(qemu_log("%s " TARGET_FMT_plx "=%x\n", __func__, addr, value));
1.1.1.3 root 122: addr >>= 2;
123: switch (addr)
124: {
125: case RW_DOUT:
1.1.1.8 ! root 126: qemu_chr_fe_write(s->chr, &ch, 1);
1.1.1.5 root 127: s->regs[R_INTR] |= 3;
1.1.1.3 root 128: s->pending_tx = 1;
129: s->regs[addr] = value;
130: break;
131: case RW_ACK_INTR:
1.1.1.5 root 132: if (s->pending_tx) {
133: value &= ~1;
1.1.1.3 root 134: s->pending_tx = 0;
1.1.1.8 ! root 135: D(qemu_log("fixedup value=%x r_intr=%x\n",
! 136: value, s->regs[R_INTR]));
1.1.1.3 root 137: }
1.1.1.5 root 138: s->regs[addr] = value;
139: s->regs[R_INTR] &= ~value;
140: D(printf("r_intr=%x\n", s->regs[R_INTR]));
1.1.1.3 root 141: break;
142: default:
143: s->regs[addr] = value;
144: break;
145: }
146: ser_update_irq(s);
1.1 root 147: }
148:
1.1.1.8 ! root 149: static const MemoryRegionOps ser_ops = {
! 150: .read = ser_read,
! 151: .write = ser_write,
! 152: .endianness = DEVICE_NATIVE_ENDIAN,
! 153: .valid = {
! 154: .min_access_size = 4,
! 155: .max_access_size = 4
! 156: }
1.1 root 157: };
158:
1.1.1.2 root 159: static void serial_receive(void *opaque, const uint8_t *buf, int size)
160: {
1.1.1.3 root 161: struct etrax_serial *s = opaque;
1.1.1.5 root 162: int i;
163:
164: /* Got a byte. */
165: if (s->rx_fifo_len >= 16) {
1.1.1.8 ! root 166: qemu_log("WARNING: UART dropped char.\n");
1.1.1.5 root 167: return;
168: }
169:
170: for (i = 0; i < size; i++) {
171: s->rx_fifo[s->rx_fifo_pos] = buf[i];
172: s->rx_fifo_pos++;
173: s->rx_fifo_pos &= 15;
174: s->rx_fifo_len++;
175: }
1.1.1.2 root 176:
1.1.1.3 root 177: ser_update_irq(s);
1.1.1.2 root 178: }
179:
180: static int serial_can_receive(void *opaque)
1.1 root 181: {
1.1.1.3 root 182: struct etrax_serial *s = opaque;
183: int r;
1.1.1.2 root 184:
1.1.1.3 root 185: /* Is the receiver enabled? */
1.1.1.5 root 186: if (!(s->regs[RW_REC_CTRL] & (1 << 3))) {
187: return 0;
188: }
1.1.1.2 root 189:
1.1.1.5 root 190: r = sizeof(s->rx_fifo) - s->rx_fifo_len;
1.1.1.3 root 191: return r;
1.1.1.2 root 192: }
193:
194: static void serial_event(void *opaque, int event)
195: {
196:
197: }
198:
1.1.1.7 root 199: static void etraxfs_ser_reset(DeviceState *d)
1.1.1.2 root 200: {
1.1.1.7 root 201: struct etrax_serial *s = container_of(d, typeof(*s), busdev.qdev);
1.1.1.2 root 202:
1.1.1.3 root 203: /* transmitter begins ready and idle. */
204: s->regs[RS_STAT_DIN] |= (1 << STAT_TR_RDY);
205: s->regs[RS_STAT_DIN] |= (1 << STAT_TR_IDLE);
1.1.1.2 root 206:
1.1.1.7 root 207: s->regs[RW_REC_CTRL] = 0x10000;
208:
209: }
210:
211: static int etraxfs_ser_init(SysBusDevice *dev)
212: {
213: struct etrax_serial *s = FROM_SYSBUS(typeof (*s), dev);
214:
1.1.1.3 root 215: sysbus_init_irq(dev, &s->irq);
1.1.1.8 ! root 216: memory_region_init_io(&s->mmio, &ser_ops, s, "etraxfs-serial", R_MAX * 4);
! 217: sysbus_init_mmio_region(dev, &s->mmio);
! 218:
1.1.1.3 root 219: s->chr = qdev_init_chardev(&dev->qdev);
220: if (s->chr)
221: qemu_chr_add_handlers(s->chr,
222: serial_can_receive, serial_receive,
223: serial_event, s);
1.1.1.4 root 224: return 0;
1.1.1.3 root 225: }
1.1.1.2 root 226:
1.1.1.7 root 227: static SysBusDeviceInfo etraxfs_ser_info = {
228: .init = etraxfs_ser_init,
229: .qdev.name = "etraxfs,serial",
230: .qdev.size = sizeof(struct etrax_serial),
231: .qdev.reset = etraxfs_ser_reset,
232: };
233:
1.1.1.3 root 234: static void etraxfs_serial_register(void)
235: {
1.1.1.7 root 236: sysbus_register_withprop(&etraxfs_ser_info);
1.1 root 237: }
1.1.1.3 root 238:
239: device_init(etraxfs_serial_register)
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.