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

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: 
1.1.1.4 ! root      125: static CPUReadMemoryFunc * const ser_read[] = {
1.1.1.3   root      126:     NULL, NULL,
                    127:     &ser_readl,
1.1       root      128: };
                    129: 
1.1.1.4 ! root      130: static CPUWriteMemoryFunc * const 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.4 ! root      164: static int 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);
1.1.1.4 ! root      181:     return 0;
1.1.1.3   root      182: }
1.1.1.2   root      183: 
1.1.1.3   root      184: static void etraxfs_serial_register(void)
                    185: {
                    186:     sysbus_register_dev("etraxfs,serial", sizeof (struct etrax_serial),
                    187:                 etraxfs_ser_init);
1.1       root      188: }
1.1.1.3   root      189: 
                    190: device_init(etraxfs_serial_register)

unix.superglobalmegacorp.com