Annotation of qemu/hw/sh_serial.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * QEMU SCI/SCIF serial port emulation
                      3:  *
                      4:  * Copyright (c) 2007 Magnus Damm
                      5:  *
                      6:  * Based on serial.c - QEMU 16450 UART emulation
                      7:  * Copyright (c) 2003-2004 Fabrice Bellard
                      8:  *
                      9:  * Permission is hereby granted, free of charge, to any person obtaining a copy
                     10:  * of this software and associated documentation files (the "Software"), to deal
                     11:  * in the Software without restriction, including without limitation the rights
                     12:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
                     13:  * copies of the Software, and to permit persons to whom the Software is
                     14:  * furnished to do so, subject to the following conditions:
                     15:  *
                     16:  * The above copyright notice and this permission notice shall be included in
                     17:  * all copies or substantial portions of the Software.
                     18:  *
                     19:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
                     20:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                     21:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
                     22:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
                     23:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
                     24:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
                     25:  * THE SOFTWARE.
                     26:  */
                     27: #include "hw.h"
                     28: #include "sh.h"
                     29: #include "qemu-char.h"
                     30: #include <assert.h>
                     31: 
                     32: //#define DEBUG_SERIAL
                     33: 
                     34: #define SH_SERIAL_FLAG_TEND (1 << 0)
                     35: #define SH_SERIAL_FLAG_TDE  (1 << 1)
                     36: #define SH_SERIAL_FLAG_RDF  (1 << 2)
                     37: #define SH_SERIAL_FLAG_BRK  (1 << 3)
                     38: #define SH_SERIAL_FLAG_DR   (1 << 4)
                     39: 
                     40: typedef struct {
                     41:     uint8_t smr;
                     42:     uint8_t brr;
                     43:     uint8_t scr;
                     44:     uint8_t dr; /* ftdr / tdr */
                     45:     uint8_t sr; /* fsr / ssr */
                     46:     uint16_t fcr;
                     47:     uint8_t sptr;
                     48: 
                     49:     uint8_t rx_fifo[16]; /* frdr / rdr */
                     50:     uint8_t rx_cnt;
                     51: 
                     52:     target_phys_addr_t base;
                     53:     int freq;
                     54:     int feat;
                     55:     int flags;
                     56: 
                     57:     CharDriverState *chr;
                     58: } sh_serial_state;
                     59: 
                     60: static void sh_serial_ioport_write(void *opaque, uint32_t offs, uint32_t val)
                     61: {
                     62:     sh_serial_state *s = opaque;
                     63:     unsigned char ch;
                     64: 
                     65: #ifdef DEBUG_SERIAL
                     66:     printf("sh_serial: write base=0x%08lx offs=0x%02x val=0x%02x\n",
                     67:           (unsigned long) s->base, offs, val);
                     68: #endif
                     69:     switch(offs) {
                     70:     case 0x00: /* SMR */
                     71:         s->smr = val & ((s->feat & SH_SERIAL_FEAT_SCIF) ? 0x7b : 0xff);
                     72:         return;
                     73:     case 0x04: /* BRR */
                     74:         s->brr = val;
                     75:        return;
                     76:     case 0x08: /* SCR */
                     77:         s->scr = val & ((s->feat & SH_SERIAL_FEAT_SCIF) ? 0xfb : 0xff);
                     78:         if (!(val & (1 << 5)))
                     79:             s->flags |= SH_SERIAL_FLAG_TEND;
                     80:         return;
                     81:     case 0x0c: /* FTDR / TDR */
                     82:         if (s->chr) {
                     83:             ch = val;
                     84:             qemu_chr_write(s->chr, &ch, 1);
                     85:        }
                     86:        s->dr = val;
                     87:        s->flags &= ~SH_SERIAL_FLAG_TDE;
                     88:         return;
                     89: #if 0
                     90:     case 0x14: /* FRDR / RDR */
                     91:         ret = 0;
                     92:         break;
                     93: #endif
                     94:     }
                     95:     if (s->feat & SH_SERIAL_FEAT_SCIF) {
                     96:         switch(offs) {
                     97:         case 0x10: /* FSR */
                     98:             if (!(val & (1 << 6)))
                     99:                 s->flags &= ~SH_SERIAL_FLAG_TEND;
                    100:             if (!(val & (1 << 5)))
                    101:                 s->flags &= ~SH_SERIAL_FLAG_TDE;
                    102:             if (!(val & (1 << 4)))
                    103:                 s->flags &= ~SH_SERIAL_FLAG_BRK;
                    104:             if (!(val & (1 << 1)))
                    105:                 s->flags &= ~SH_SERIAL_FLAG_RDF;
                    106:             if (!(val & (1 << 0)))
                    107:                 s->flags &= ~SH_SERIAL_FLAG_DR;
                    108:             return;
                    109:         case 0x18: /* FCR */
                    110:             s->fcr = val;
                    111:             return;
                    112:         case 0x20: /* SPTR */
                    113:             s->sptr = val;
                    114:             return;
                    115:         case 0x24: /* LSR */
                    116:             return;
                    117:         }
                    118:     }
                    119:     else {
                    120: #if 0
                    121:         switch(offs) {
                    122:         case 0x0c:
                    123:             ret = s->dr;
                    124:             break;
                    125:         case 0x10:
                    126:             ret = 0;
                    127:             break;
                    128:         case 0x1c:
                    129:             ret = s->sptr;
                    130:             break;
                    131:         }
                    132: #endif
                    133:     }
                    134: 
                    135:     fprintf(stderr, "sh_serial: unsupported write to 0x%02x\n", offs);
                    136:     assert(0);
                    137: }
                    138: 
                    139: static uint32_t sh_serial_ioport_read(void *opaque, uint32_t offs)
                    140: {
                    141:     sh_serial_state *s = opaque;
                    142:     uint32_t ret = ~0;
                    143: 
                    144: #if 0
                    145:     switch(offs) {
                    146:     case 0x00:
                    147:         ret = s->smr;
                    148:         break;
                    149:     case 0x04:
                    150:         ret = s->brr;
                    151:        break;
                    152:     case 0x08:
                    153:         ret = s->scr;
                    154:         break;
                    155:     case 0x14:
                    156:         ret = 0;
                    157:         break;
                    158:     }
                    159: #endif
                    160:     if (s->feat & SH_SERIAL_FEAT_SCIF) {
                    161:         switch(offs) {
                    162:         case 0x10: /* FSR */
                    163:             ret = 0;
                    164:             if (s->flags & SH_SERIAL_FLAG_TEND)
                    165:                 ret |= (1 << 6);
                    166:             if (s->flags & SH_SERIAL_FLAG_TDE)
                    167:                 ret |= (1 << 5);
                    168:             if (s->flags & SH_SERIAL_FLAG_BRK)
                    169:                 ret |= (1 << 4);
                    170:             if (s->flags & SH_SERIAL_FLAG_RDF)
                    171:                 ret |= (1 << 1);
                    172:             if (s->flags & SH_SERIAL_FLAG_DR)
                    173:                 ret |= (1 << 0);
                    174: 
                    175:            if (s->scr & (1 << 5))
                    176:                 s->flags |= SH_SERIAL_FLAG_TDE | SH_SERIAL_FLAG_TEND;
                    177: 
                    178:             break;
                    179: #if 0
                    180:         case 0x18:
                    181:             ret = s->fcr;
                    182:             break;
                    183: #endif
                    184:         case 0x1c:
                    185:             ret = s->rx_cnt;
                    186:             break;
                    187:         case 0x20:
                    188:             ret = s->sptr;
                    189:             break;
                    190:         case 0x24:
                    191:             ret = 0;
                    192:             break;
                    193:         }
                    194:     }
                    195:     else {
                    196: #if 0
                    197:         switch(offs) {
                    198:         case 0x0c:
                    199:             ret = s->dr;
                    200:             break;
                    201:         case 0x10:
                    202:             ret = 0;
                    203:             break;
                    204:         case 0x1c:
                    205:             ret = s->sptr;
                    206:             break;
                    207:         }
                    208: #endif
                    209:     }
                    210: #ifdef DEBUG_SERIAL
                    211:     printf("sh_serial: read base=0x%08lx offs=0x%02x val=0x%x\n",
                    212:           (unsigned long) s->base, offs, ret);
                    213: #endif
                    214: 
                    215:     if (ret & ~((1 << 16) - 1)) {
                    216:         fprintf(stderr, "sh_serial: unsupported read from 0x%02x\n", offs);
                    217:        assert(0);
                    218:     }
                    219: 
                    220:     return ret;
                    221: }
                    222: 
                    223: static int sh_serial_can_receive(sh_serial_state *s)
                    224: {
                    225:     return 0;
                    226: }
                    227: 
                    228: static void sh_serial_receive_byte(sh_serial_state *s, int ch)
                    229: {
                    230: }
                    231: 
                    232: static void sh_serial_receive_break(sh_serial_state *s)
                    233: {
                    234: }
                    235: 
                    236: static int sh_serial_can_receive1(void *opaque)
                    237: {
                    238:     sh_serial_state *s = opaque;
                    239:     return sh_serial_can_receive(s);
                    240: }
                    241: 
                    242: static void sh_serial_receive1(void *opaque, const uint8_t *buf, int size)
                    243: {
                    244:     sh_serial_state *s = opaque;
                    245:     sh_serial_receive_byte(s, buf[0]);
                    246: }
                    247: 
                    248: static void sh_serial_event(void *opaque, int event)
                    249: {
                    250:     sh_serial_state *s = opaque;
                    251:     if (event == CHR_EVENT_BREAK)
                    252:         sh_serial_receive_break(s);
                    253: }
                    254: 
                    255: static uint32_t sh_serial_read (void *opaque, target_phys_addr_t addr)
                    256: {
                    257:     sh_serial_state *s = opaque;
                    258:     return sh_serial_ioport_read(s, addr - s->base);
                    259: }
                    260: 
                    261: static void sh_serial_write (void *opaque,
                    262:                              target_phys_addr_t addr, uint32_t value)
                    263: {
                    264:     sh_serial_state *s = opaque;
                    265:     sh_serial_ioport_write(s, addr - s->base, value);
                    266: }
                    267: 
                    268: static CPUReadMemoryFunc *sh_serial_readfn[] = {
                    269:     &sh_serial_read,
                    270:     &sh_serial_read,
                    271:     &sh_serial_read,
                    272: };
                    273: 
                    274: static CPUWriteMemoryFunc *sh_serial_writefn[] = {
                    275:     &sh_serial_write,
                    276:     &sh_serial_write,
                    277:     &sh_serial_write,
                    278: };
                    279: 
                    280: void sh_serial_init (target_phys_addr_t base, int feat,
                    281:                     uint32_t freq, CharDriverState *chr)
                    282: {
                    283:     sh_serial_state *s;
                    284:     int s_io_memory;
                    285: 
                    286:     s = qemu_mallocz(sizeof(sh_serial_state));
                    287:     if (!s)
                    288:         return;
                    289: 
                    290:     s->base = base;
                    291:     s->feat = feat;
                    292:     s->flags = SH_SERIAL_FLAG_TEND | SH_SERIAL_FLAG_TDE;
                    293: 
                    294:     s->smr = 0;
                    295:     s->brr = 0xff;
                    296:     s->scr = 1 << 5; /* pretend that TX is enabled so early printk works */
                    297:     s->sptr = 0;
                    298: 
                    299:     if (feat & SH_SERIAL_FEAT_SCIF) {
                    300:         s->fcr = 0;
                    301:     }
                    302:     else {
                    303:         s->dr = 0xff;
                    304:     }
                    305: 
                    306:     s->rx_cnt = 0;
                    307: 
                    308:     s_io_memory = cpu_register_io_memory(0, sh_serial_readfn,
                    309:                                         sh_serial_writefn, s);
                    310:     cpu_register_physical_memory(base, 0x28, s_io_memory);
                    311: 
                    312:     s->chr = chr;
                    313: 
                    314:     if (chr)
                    315:         qemu_chr_add_handlers(chr, sh_serial_can_receive1, sh_serial_receive1,
                    316:                              sh_serial_event, s);
                    317: }

unix.superglobalmegacorp.com

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