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

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       root       27: 
1.1.1.2   root       28: #define D(x)
1.1       root       29: 
1.1.1.3 ! root       30: #define RW_TR_CTRL     (0x00 / 4)
        !            31: #define RW_TR_DMA_EN   (0x04 / 4)
        !            32: #define RW_REC_CTRL    (0x08 / 4)
        !            33: #define RW_DOUT        (0x1c / 4)
        !            34: #define RS_STAT_DIN    (0x20 / 4)
        !            35: #define R_STAT_DIN     (0x24 / 4)
        !            36: #define RW_INTR_MASK   (0x2c / 4)
        !            37: #define RW_ACK_INTR    (0x30 / 4)
        !            38: #define R_INTR         (0x34 / 4)
        !            39: #define R_MASKED_INTR  (0x38 / 4)
        !            40: #define R_MAX          (0x3c / 4)
1.1.1.2   root       41: 
                     42: #define STAT_DAV     16
                     43: #define STAT_TR_IDLE 22
                     44: #define STAT_TR_RDY  24
                     45: 
1.1.1.3 ! root       46: struct etrax_serial
1.1.1.2   root       47: {
1.1.1.3 ! root       48:     SysBusDevice busdev;
        !            49:     CharDriverState *chr;
        !            50:     qemu_irq irq;
1.1.1.2   root       51: 
1.1.1.3 ! root       52:     /* This pending thing is a hack.  */
        !            53:     int pending_tx;
1.1.1.2   root       54: 
1.1.1.3 ! root       55:     /* Control registers.  */
        !            56:     uint32_t regs[R_MAX];
        !            57: };
1.1.1.2   root       58: 
1.1.1.3 ! root       59: static void ser_update_irq(struct etrax_serial *s)
1.1       root       60: {
1.1.1.3 ! root       61:     s->regs[R_INTR] &= ~(s->regs[RW_ACK_INTR]);
        !            62:     s->regs[R_MASKED_INTR] = s->regs[R_INTR] & s->regs[RW_INTR_MASK];
        !            63: 
        !            64:     qemu_set_irq(s->irq, !!s->regs[R_MASKED_INTR]);
        !            65:     s->regs[RW_ACK_INTR] = 0;
1.1       root       66: }
                     67: 
                     68: static uint32_t ser_readl (void *opaque, target_phys_addr_t addr)
                     69: {
1.1.1.3 ! root       70:     struct etrax_serial *s = opaque;
        !            71:     D(CPUState *env = s->env);
        !            72:     uint32_t r = 0;
        !            73: 
        !            74:     addr >>= 2;
        !            75:     switch (addr)
        !            76:     {
        !            77:         case R_STAT_DIN:
        !            78:             r = s->regs[RS_STAT_DIN];
        !            79:             break;
        !            80:         case RS_STAT_DIN:
        !            81:             r = s->regs[addr];
        !            82:             /* Read side-effect: clear dav.  */
        !            83:             s->regs[addr] &= ~(1 << STAT_DAV);
        !            84:             break;
        !            85:         default:
        !            86:             r = s->regs[addr];
        !            87:             D(printf ("%s %x=%x\n", __func__, addr, r));
        !            88:             break;
        !            89:     }
        !            90:     return r;
1.1       root       91: }
                     92: 
                     93: static void
                     94: ser_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
                     95: {
1.1.1.3 ! root       96:     struct etrax_serial *s = opaque;
        !            97:     unsigned char ch = value;
        !            98:     D(CPUState *env = s->env);
        !            99: 
        !           100:     D(printf ("%s %x %x\n",  __func__, addr, value));
        !           101:     addr >>= 2;
        !           102:     switch (addr)
        !           103:     {
        !           104:         case RW_DOUT:
        !           105:             qemu_chr_write(s->chr, &ch, 1);
        !           106:             s->regs[R_INTR] |= 1;
        !           107:             s->pending_tx = 1;
        !           108:             s->regs[addr] = value;
        !           109:             break;
        !           110:         case RW_ACK_INTR:
        !           111:             s->regs[addr] = value;
        !           112:             if (s->pending_tx && (s->regs[addr] & 1)) {
        !           113:                 s->regs[R_INTR] |= 1;
        !           114:                 s->pending_tx = 0;
        !           115:                 s->regs[addr] &= ~1;
        !           116:             }
        !           117:             break;
        !           118:         default:
        !           119:             s->regs[addr] = value;
        !           120:             break;
        !           121:     }
        !           122:     ser_update_irq(s);
1.1       root      123: }
                    124: 
                    125: static CPUReadMemoryFunc *ser_read[] = {
1.1.1.3 ! root      126:     NULL, NULL,
        !           127:     &ser_readl,
1.1       root      128: };
                    129: 
                    130: static CPUWriteMemoryFunc *ser_write[] = {
1.1.1.3 ! root      131:     NULL, NULL,
        !           132:     &ser_writel,
1.1       root      133: };
                    134: 
1.1.1.2   root      135: static void serial_receive(void *opaque, const uint8_t *buf, int size)
                    136: {
1.1.1.3 ! root      137:     struct etrax_serial *s = opaque;
1.1.1.2   root      138: 
1.1.1.3 ! root      139:     s->regs[R_INTR] |= 8;
        !           140:     s->regs[RS_STAT_DIN] &= ~0xff;
        !           141:     s->regs[RS_STAT_DIN] |= (buf[0] & 0xff);
        !           142:     s->regs[RS_STAT_DIN] |= (1 << STAT_DAV); /* dav.  */
        !           143:     ser_update_irq(s);
1.1.1.2   root      144: }
                    145: 
                    146: static int serial_can_receive(void *opaque)
1.1       root      147: {
1.1.1.3 ! root      148:     struct etrax_serial *s = opaque;
        !           149:     int r;
1.1.1.2   root      150: 
1.1.1.3 ! root      151:     /* Is the receiver enabled?  */
        !           152:     r = s->regs[RW_REC_CTRL] & 1;
1.1.1.2   root      153: 
1.1.1.3 ! root      154:     /* Pending rx data?  */
        !           155:     r |= !(s->regs[R_INTR] & 8);
        !           156:     return r;
1.1.1.2   root      157: }
                    158: 
                    159: static void serial_event(void *opaque, int event)
                    160: {
                    161: 
                    162: }
                    163: 
1.1.1.3 ! root      164: static void etraxfs_ser_init(SysBusDevice *dev)
1.1.1.2   root      165: {
1.1.1.3 ! root      166:     struct etrax_serial *s = FROM_SYSBUS(typeof (*s), dev);
        !           167:     int ser_regs;
1.1.1.2   root      168: 
1.1.1.3 ! root      169:     /* transmitter begins ready and idle.  */
        !           170:     s->regs[RS_STAT_DIN] |= (1 << STAT_TR_RDY);
        !           171:     s->regs[RS_STAT_DIN] |= (1 << STAT_TR_IDLE);
1.1.1.2   root      172: 
1.1.1.3 ! root      173:     sysbus_init_irq(dev, &s->irq);
        !           174:     ser_regs = cpu_register_io_memory(ser_read, ser_write, s);
        !           175:     sysbus_init_mmio(dev, R_MAX * 4, ser_regs);
        !           176:     s->chr = qdev_init_chardev(&dev->qdev);
        !           177:     if (s->chr)
        !           178:         qemu_chr_add_handlers(s->chr,
        !           179:                       serial_can_receive, serial_receive,
        !           180:                       serial_event, s);
        !           181: }
1.1.1.2   root      182: 
1.1.1.3 ! root      183: static void etraxfs_serial_register(void)
        !           184: {
        !           185:     sysbus_register_dev("etraxfs,serial", sizeof (struct etrax_serial),
        !           186:                 etraxfs_ser_init);
1.1       root      187: }
1.1.1.3 ! root      188: 
        !           189: 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.