|
|
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;
1.1.1.9 ! root 81: D(CPUCRISState *env = s->env);
1.1.1.3 root 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.9 ! root 119: D(CPUCRISState *env = s->env);
1.1.1.3 root 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);
1.1.1.9 ! root 217: sysbus_init_mmio(dev, &s->mmio);
1.1.1.8 root 218:
1.1.1.9 ! root 219: s->chr = qemu_char_get_next_serial();
1.1.1.3 root 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.9 ! root 227: static void etraxfs_ser_class_init(ObjectClass *klass, void *data)
! 228: {
! 229: DeviceClass *dc = DEVICE_CLASS(klass);
! 230: SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
! 231:
! 232: k->init = etraxfs_ser_init;
! 233: dc->reset = etraxfs_ser_reset;
! 234: }
! 235:
! 236: static TypeInfo etraxfs_ser_info = {
! 237: .name = "etraxfs,serial",
! 238: .parent = TYPE_SYS_BUS_DEVICE,
! 239: .instance_size = sizeof(struct etrax_serial),
! 240: .class_init = etraxfs_ser_class_init,
1.1.1.7 root 241: };
242:
1.1.1.9 ! root 243: static void etraxfs_serial_register_types(void)
1.1.1.3 root 244: {
1.1.1.9 ! root 245: type_register_static(&etraxfs_ser_info);
1.1 root 246: }
1.1.1.3 root 247:
1.1.1.9 ! root 248: type_init(etraxfs_serial_register_types)
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.