Annotation of qemu/hw/etraxfs_ser.c, revision 1.1.1.8

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)

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.