|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.