Commit 2f062c72275938cc8fcbf0ce083b73a35d6a5329
1 parent
cd1a3f68
Stand-alone SCI/SCIF emulation code, by Magnus Damm.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3270 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
6 changed files
with
325 additions
and
585 deletions
Makefile.target
| ... | ... | @@ -476,7 +476,7 @@ CPPFLAGS += -DHAS_AUDIO |
| 476 | 476 | endif |
| 477 | 477 | ifeq ($(TARGET_BASE_ARCH), sh4) |
| 478 | 478 | VL_OBJS+= shix.o r2d.o sh7750.o sh7750_regnames.o tc58128.o |
| 479 | -VL_OBJS+= sh_timer.o ptimer.o | |
| 479 | +VL_OBJS+= sh_timer.o ptimer.o sh_serial.o | |
| 480 | 480 | endif |
| 481 | 481 | ifeq ($(TARGET_BASE_ARCH), m68k) |
| 482 | 482 | VL_OBJS+= an5206.o mcf5206.o ptimer.o mcf_uart.o mcf_intc.o mcf5208.o mcf_fec.o | ... | ... |
hw/sh7750.c
| ... | ... | @@ -27,13 +27,6 @@ |
| 27 | 27 | #include "sh7750_regs.h" |
| 28 | 28 | #include "sh7750_regnames.h" |
| 29 | 29 | |
| 30 | -typedef struct { | |
| 31 | - uint8_t data[16]; | |
| 32 | - uint8_t length; /* Number of characters in the FIFO */ | |
| 33 | - uint8_t write_idx; /* Index of first character to write */ | |
| 34 | - uint8_t read_idx; /* Index of first character to read */ | |
| 35 | -} fifo; | |
| 36 | - | |
| 37 | 30 | #define NB_DEVICES 4 |
| 38 | 31 | |
| 39 | 32 | typedef struct SH7750State { |
| ... | ... | @@ -43,27 +36,6 @@ typedef struct SH7750State { |
| 43 | 36 | uint32_t periph_freq; |
| 44 | 37 | /* SDRAM controller */ |
| 45 | 38 | uint16_t rfcr; |
| 46 | - /* First serial port */ | |
| 47 | - CharDriverState *serial1; | |
| 48 | - uint8_t scscr1; | |
| 49 | - uint8_t scsmr1; | |
| 50 | - uint8_t scbrr1; | |
| 51 | - uint8_t scssr1; | |
| 52 | - uint8_t scssr1_read; | |
| 53 | - uint8_t sctsr1; | |
| 54 | - uint8_t sctsr1_loaded; | |
| 55 | - uint8_t sctdr1; | |
| 56 | - uint8_t scrdr1; | |
| 57 | - /* Second serial port */ | |
| 58 | - CharDriverState *serial2; | |
| 59 | - uint16_t sclsr2; | |
| 60 | - uint16_t scscr2; | |
| 61 | - uint16_t scfcr2; | |
| 62 | - uint16_t scfsr2; | |
| 63 | - uint16_t scsmr2; | |
| 64 | - uint8_t scbrr2; | |
| 65 | - fifo serial2_receive_fifo; | |
| 66 | - fifo serial2_transmit_fifo; | |
| 67 | 39 | /* IO ports */ |
| 68 | 40 | uint16_t gpioic; |
| 69 | 41 | uint32_t pctra; |
| ... | ... | @@ -84,263 +56,6 @@ typedef struct SH7750State { |
| 84 | 56 | |
| 85 | 57 | } SH7750State; |
| 86 | 58 | |
| 87 | -/********************************************************************** | |
| 88 | - First serial port | |
| 89 | -**********************************************************************/ | |
| 90 | - | |
| 91 | -static int serial1_can_receive(void *opaque) | |
| 92 | -{ | |
| 93 | - SH7750State *s = opaque; | |
| 94 | - | |
| 95 | - return s->scscr1 & SH7750_SCSCR_RE; | |
| 96 | -} | |
| 97 | - | |
| 98 | -static void serial1_receive_char(SH7750State * s, uint8_t c) | |
| 99 | -{ | |
| 100 | - if (s->scssr1 & SH7750_SCSSR1_RDRF) { | |
| 101 | - s->scssr1 |= SH7750_SCSSR1_ORER; | |
| 102 | - return; | |
| 103 | - } | |
| 104 | - | |
| 105 | - s->scrdr1 = c; | |
| 106 | - s->scssr1 |= SH7750_SCSSR1_RDRF; | |
| 107 | -} | |
| 108 | - | |
| 109 | -static void serial1_receive(void *opaque, const uint8_t * buf, int size) | |
| 110 | -{ | |
| 111 | - SH7750State *s = opaque; | |
| 112 | - int i; | |
| 113 | - | |
| 114 | - for (i = 0; i < size; i++) { | |
| 115 | - serial1_receive_char(s, buf[i]); | |
| 116 | - } | |
| 117 | -} | |
| 118 | - | |
| 119 | -static void serial1_event(void *opaque, int event) | |
| 120 | -{ | |
| 121 | - assert(0); | |
| 122 | -} | |
| 123 | - | |
| 124 | -static void serial1_maybe_send(SH7750State * s) | |
| 125 | -{ | |
| 126 | - uint8_t c; | |
| 127 | - | |
| 128 | - if (s->scssr1 & SH7750_SCSSR1_TDRE) | |
| 129 | - return; | |
| 130 | - c = s->sctdr1; | |
| 131 | - s->scssr1 |= SH7750_SCSSR1_TDRE | SH7750_SCSSR1_TEND; | |
| 132 | - if (s->scscr1 & SH7750_SCSCR_TIE) { | |
| 133 | - fprintf(stderr, "interrupts for serial port 1 not implemented\n"); | |
| 134 | - assert(0); | |
| 135 | - } | |
| 136 | - /* XXXXX Check for errors in write */ | |
| 137 | - qemu_chr_write(s->serial1, &c, 1); | |
| 138 | -} | |
| 139 | - | |
| 140 | -static void serial1_change_scssr1(SH7750State * s, uint8_t mem_value) | |
| 141 | -{ | |
| 142 | - uint8_t new_flags; | |
| 143 | - | |
| 144 | - /* If transmit disable, TDRE and TEND stays up */ | |
| 145 | - if ((s->scscr1 & SH7750_SCSCR_TE) == 0) { | |
| 146 | - mem_value |= SH7750_SCSSR1_TDRE | SH7750_SCSSR1_TEND; | |
| 147 | - } | |
| 148 | - | |
| 149 | - /* Only clear bits which have been read before and do not set any bit | |
| 150 | - in the flags */ | |
| 151 | - new_flags = s->scssr1 & ~s->scssr1_read; /* Preserve unread flags */ | |
| 152 | - new_flags &= mem_value | ~s->scssr1_read; /* Clear read flags */ | |
| 153 | - | |
| 154 | - s->scssr1 = (new_flags & 0xf8) | (mem_value & 1); | |
| 155 | - s->scssr1_read &= mem_value; | |
| 156 | - | |
| 157 | - /* If TDRE has been cleared, TEND will also be cleared */ | |
| 158 | - if ((s->scssr1 & SH7750_SCSSR1_TDRE) == 0) { | |
| 159 | - s->scssr1 &= ~SH7750_SCSSR1_TEND; | |
| 160 | - } | |
| 161 | - | |
| 162 | - /* Check for transmission to start */ | |
| 163 | - serial1_maybe_send(s); | |
| 164 | -} | |
| 165 | - | |
| 166 | -static void serial1_update_parameters(SH7750State * s) | |
| 167 | -{ | |
| 168 | - QEMUSerialSetParams ssp; | |
| 169 | - | |
| 170 | - if (s->scsmr1 & SH7750_SCSMR_CHR_7) | |
| 171 | - ssp.data_bits = 7; | |
| 172 | - else | |
| 173 | - ssp.data_bits = 8; | |
| 174 | - if (s->scsmr1 & SH7750_SCSMR_PE) { | |
| 175 | - if (s->scsmr1 & SH7750_SCSMR_PM_ODD) | |
| 176 | - ssp.parity = 'O'; | |
| 177 | - else | |
| 178 | - ssp.parity = 'E'; | |
| 179 | - } else | |
| 180 | - ssp.parity = 'N'; | |
| 181 | - if (s->scsmr1 & SH7750_SCSMR_STOP_2) | |
| 182 | - ssp.stop_bits = 2; | |
| 183 | - else | |
| 184 | - ssp.stop_bits = 1; | |
| 185 | - fprintf(stderr, "SCSMR1=%04x SCBRR1=%02x\n", s->scsmr1, s->scbrr1); | |
| 186 | - ssp.speed = s->periph_freq / | |
| 187 | - (32 * s->scbrr1 * (1 << (2 * (s->scsmr1 & 3)))) - 1; | |
| 188 | - fprintf(stderr, "data bits=%d, stop bits=%d, parity=%c, speed=%d\n", | |
| 189 | - ssp.data_bits, ssp.stop_bits, ssp.parity, ssp.speed); | |
| 190 | - qemu_chr_ioctl(s->serial1, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp); | |
| 191 | -} | |
| 192 | - | |
| 193 | -static void scscr1_changed(SH7750State * s) | |
| 194 | -{ | |
| 195 | - if (s->scscr1 & (SH7750_SCSCR_TE | SH7750_SCSCR_RE)) { | |
| 196 | - if (!s->serial1) { | |
| 197 | - fprintf(stderr, "serial port 1 not bound to anything\n"); | |
| 198 | - assert(0); | |
| 199 | - } | |
| 200 | - serial1_update_parameters(s); | |
| 201 | - } | |
| 202 | - if ((s->scscr1 & SH7750_SCSCR_RE) == 0) { | |
| 203 | - s->scssr1 |= SH7750_SCSSR1_TDRE; | |
| 204 | - } | |
| 205 | -} | |
| 206 | - | |
| 207 | -static void init_serial1(SH7750State * s, int serial_nb) | |
| 208 | -{ | |
| 209 | - CharDriverState *chr; | |
| 210 | - | |
| 211 | - s->scssr1 = 0x84; | |
| 212 | - chr = serial_hds[serial_nb]; | |
| 213 | - if (!chr) { | |
| 214 | - fprintf(stderr, | |
| 215 | - "no serial port associated to SH7750 first serial port\n"); | |
| 216 | - return; | |
| 217 | - } | |
| 218 | - | |
| 219 | - s->serial1 = chr; | |
| 220 | - qemu_chr_add_handlers(chr, serial1_can_receive, | |
| 221 | - serial1_receive, serial1_event, s); | |
| 222 | -} | |
| 223 | - | |
| 224 | -/********************************************************************** | |
| 225 | - Second serial port | |
| 226 | -**********************************************************************/ | |
| 227 | - | |
| 228 | -static int serial2_can_receive(void *opaque) | |
| 229 | -{ | |
| 230 | - SH7750State *s = opaque; | |
| 231 | - static uint8_t max_fifo_size[] = { 15, 1, 4, 6, 8, 10, 12, 14 }; | |
| 232 | - | |
| 233 | - return s->serial2_receive_fifo.length < | |
| 234 | - max_fifo_size[(s->scfcr2 >> 9) & 7]; | |
| 235 | -} | |
| 236 | - | |
| 237 | -static void serial2_adjust_receive_flags(SH7750State * s) | |
| 238 | -{ | |
| 239 | - static uint8_t max_fifo_size[] = { 1, 4, 8, 14 }; | |
| 240 | - | |
| 241 | - /* XXXXX Add interrupt generation */ | |
| 242 | - if (s->serial2_receive_fifo.length >= | |
| 243 | - max_fifo_size[(s->scfcr2 >> 7) & 3]) { | |
| 244 | - s->scfsr2 |= SH7750_SCFSR2_RDF; | |
| 245 | - s->scfsr2 &= ~SH7750_SCFSR2_DR; | |
| 246 | - } else { | |
| 247 | - s->scfsr2 &= ~SH7750_SCFSR2_RDF; | |
| 248 | - if (s->serial2_receive_fifo.length > 0) | |
| 249 | - s->scfsr2 |= SH7750_SCFSR2_DR; | |
| 250 | - else | |
| 251 | - s->scfsr2 &= ~SH7750_SCFSR2_DR; | |
| 252 | - } | |
| 253 | -} | |
| 254 | - | |
| 255 | -static void serial2_append_char(SH7750State * s, uint8_t c) | |
| 256 | -{ | |
| 257 | - if (s->serial2_receive_fifo.length == 16) { | |
| 258 | - /* Overflow */ | |
| 259 | - s->sclsr2 |= SH7750_SCLSR2_ORER; | |
| 260 | - return; | |
| 261 | - } | |
| 262 | - | |
| 263 | - s->serial2_receive_fifo.data[s->serial2_receive_fifo.write_idx++] = c; | |
| 264 | - s->serial2_receive_fifo.length++; | |
| 265 | - serial2_adjust_receive_flags(s); | |
| 266 | -} | |
| 267 | - | |
| 268 | -static void serial2_receive(void *opaque, const uint8_t * buf, int size) | |
| 269 | -{ | |
| 270 | - SH7750State *s = opaque; | |
| 271 | - int i; | |
| 272 | - | |
| 273 | - for (i = 0; i < size; i++) | |
| 274 | - serial2_append_char(s, buf[i]); | |
| 275 | -} | |
| 276 | - | |
| 277 | -static void serial2_event(void *opaque, int event) | |
| 278 | -{ | |
| 279 | - /* XXXXX */ | |
| 280 | - assert(0); | |
| 281 | -} | |
| 282 | - | |
| 283 | -static void serial2_update_parameters(SH7750State * s) | |
| 284 | -{ | |
| 285 | - QEMUSerialSetParams ssp; | |
| 286 | - | |
| 287 | - if (s->scsmr2 & SH7750_SCSMR_CHR_7) | |
| 288 | - ssp.data_bits = 7; | |
| 289 | - else | |
| 290 | - ssp.data_bits = 8; | |
| 291 | - if (s->scsmr2 & SH7750_SCSMR_PE) { | |
| 292 | - if (s->scsmr2 & SH7750_SCSMR_PM_ODD) | |
| 293 | - ssp.parity = 'O'; | |
| 294 | - else | |
| 295 | - ssp.parity = 'E'; | |
| 296 | - } else | |
| 297 | - ssp.parity = 'N'; | |
| 298 | - if (s->scsmr2 & SH7750_SCSMR_STOP_2) | |
| 299 | - ssp.stop_bits = 2; | |
| 300 | - else | |
| 301 | - ssp.stop_bits = 1; | |
| 302 | - fprintf(stderr, "SCSMR2=%04x SCBRR2=%02x\n", s->scsmr2, s->scbrr2); | |
| 303 | - ssp.speed = s->periph_freq / | |
| 304 | - (32 * s->scbrr2 * (1 << (2 * (s->scsmr2 & 3)))) - 1; | |
| 305 | - fprintf(stderr, "data bits=%d, stop bits=%d, parity=%c, speed=%d\n", | |
| 306 | - ssp.data_bits, ssp.stop_bits, ssp.parity, ssp.speed); | |
| 307 | - qemu_chr_ioctl(s->serial2, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp); | |
| 308 | -} | |
| 309 | - | |
| 310 | -static void scscr2_changed(SH7750State * s) | |
| 311 | -{ | |
| 312 | - if (s->scscr2 & (SH7750_SCSCR_TE | SH7750_SCSCR_RE)) { | |
| 313 | - if (!s->serial2) { | |
| 314 | - fprintf(stderr, "serial port 2 not bound to anything\n"); | |
| 315 | - assert(0); | |
| 316 | - } | |
| 317 | - serial2_update_parameters(s); | |
| 318 | - } | |
| 319 | -} | |
| 320 | - | |
| 321 | -static void init_serial2(SH7750State * s, int serial_nb) | |
| 322 | -{ | |
| 323 | - CharDriverState *chr; | |
| 324 | - | |
| 325 | - s->scfsr2 = 0x0060; | |
| 326 | - | |
| 327 | - chr = serial_hds[serial_nb]; | |
| 328 | - if (!chr) { | |
| 329 | - fprintf(stderr, | |
| 330 | - "no serial port associated to SH7750 second serial port\n"); | |
| 331 | - return; | |
| 332 | - } | |
| 333 | - | |
| 334 | - s->serial2 = chr; | |
| 335 | - qemu_chr_add_handlers(chr, serial2_can_receive, | |
| 336 | - serial2_receive, serial1_event, s); | |
| 337 | -} | |
| 338 | - | |
| 339 | -static void init_serial_ports(SH7750State * s) | |
| 340 | -{ | |
| 341 | - init_serial1(s, 0); | |
| 342 | - init_serial2(s, 1); | |
| 343 | -} | |
| 344 | 59 | |
| 345 | 60 | /********************************************************************** |
| 346 | 61 | I/O ports |
| ... | ... | @@ -472,17 +187,7 @@ static void ignore_access(const char *kind, target_phys_addr_t addr) |
| 472 | 187 | |
| 473 | 188 | static uint32_t sh7750_mem_readb(void *opaque, target_phys_addr_t addr) |
| 474 | 189 | { |
| 475 | - SH7750State *s = opaque; | |
| 476 | - uint8_t r; | |
| 477 | - | |
| 478 | 190 | switch (addr) { |
| 479 | - case SH7750_SCSSR1_A7: | |
| 480 | - r = s->scssr1; | |
| 481 | - s->scssr1_read |= r; | |
| 482 | - return s->scssr1; | |
| 483 | - case SH7750_SCRDR1_A7: | |
| 484 | - s->scssr1 &= ~SH7750_SCSSR1_RDRF; | |
| 485 | - return s->scrdr1; | |
| 486 | 191 | default: |
| 487 | 192 | error_access("byte read", addr); |
| 488 | 193 | assert(0); |
| ... | ... | @@ -492,20 +197,12 @@ static uint32_t sh7750_mem_readb(void *opaque, target_phys_addr_t addr) |
| 492 | 197 | static uint32_t sh7750_mem_readw(void *opaque, target_phys_addr_t addr) |
| 493 | 198 | { |
| 494 | 199 | SH7750State *s = opaque; |
| 495 | - uint16_t r; | |
| 496 | 200 | |
| 497 | 201 | switch (addr) { |
| 498 | 202 | case SH7750_RFCR_A7: |
| 499 | 203 | fprintf(stderr, |
| 500 | 204 | "Read access to refresh count register, incrementing\n"); |
| 501 | 205 | return s->rfcr++; |
| 502 | - case SH7750_SCLSR2_A7: | |
| 503 | - /* Read and clear overflow bit */ | |
| 504 | - r = s->sclsr2; | |
| 505 | - s->sclsr2 = 0; | |
| 506 | - return r; | |
| 507 | - case SH7750_SCSFR2_A7: | |
| 508 | - return s->scfsr2; | |
| 509 | 206 | case SH7750_PDTRA_A7: |
| 510 | 207 | return porta_lines(s); |
| 511 | 208 | case SH7750_PDTRB_A7: |
| ... | ... | @@ -554,34 +251,12 @@ static uint32_t sh7750_mem_readl(void *opaque, target_phys_addr_t addr) |
| 554 | 251 | static void sh7750_mem_writeb(void *opaque, target_phys_addr_t addr, |
| 555 | 252 | uint32_t mem_value) |
| 556 | 253 | { |
| 557 | - SH7750State *s = opaque; | |
| 558 | - | |
| 559 | 254 | switch (addr) { |
| 560 | 255 | /* PRECHARGE ? XXXXX */ |
| 561 | 256 | case SH7750_PRECHARGE0_A7: |
| 562 | 257 | case SH7750_PRECHARGE1_A7: |
| 563 | 258 | ignore_access("byte write", addr); |
| 564 | 259 | return; |
| 565 | - case SH7750_SCBRR2_A7: | |
| 566 | - s->scbrr2 = mem_value; | |
| 567 | - return; | |
| 568 | - case SH7750_SCSCR1_A7: | |
| 569 | - s->scscr1 = mem_value; | |
| 570 | - scscr1_changed(s); | |
| 571 | - return; | |
| 572 | - case SH7750_SCSMR1_A7: | |
| 573 | - s->scsmr1 = mem_value; | |
| 574 | - return; | |
| 575 | - case SH7750_SCBRR1_A7: | |
| 576 | - s->scbrr1 = mem_value; | |
| 577 | - return; | |
| 578 | - case SH7750_SCTDR1_A7: | |
| 579 | - s->scssr1 &= ~SH7750_SCSSR1_TEND; | |
| 580 | - s->sctdr1 = mem_value; | |
| 581 | - return; | |
| 582 | - case SH7750_SCSSR1_A7: | |
| 583 | - serial1_change_scssr1(s, mem_value); | |
| 584 | - return; | |
| 585 | 260 | default: |
| 586 | 261 | error_access("byte write", addr); |
| 587 | 262 | assert(0); |
| ... | ... | @@ -596,8 +271,6 @@ static void sh7750_mem_writew(void *opaque, target_phys_addr_t addr, |
| 596 | 271 | |
| 597 | 272 | switch (addr) { |
| 598 | 273 | /* SDRAM controller */ |
| 599 | - case SH7750_SCBRR1_A7: | |
| 600 | - case SH7750_SCBRR2_A7: | |
| 601 | 274 | case SH7750_BCR2_A7: |
| 602 | 275 | case SH7750_BCR3_A7: |
| 603 | 276 | case SH7750_RTCOR_A7: |
| ... | ... | @@ -620,19 +293,6 @@ static void sh7750_mem_writew(void *opaque, target_phys_addr_t addr, |
| 620 | 293 | fprintf(stderr, "Write access to refresh count register\n"); |
| 621 | 294 | s->rfcr = mem_value; |
| 622 | 295 | return; |
| 623 | - case SH7750_SCLSR2_A7: | |
| 624 | - s->sclsr2 = mem_value; | |
| 625 | - return; | |
| 626 | - case SH7750_SCSCR2_A7: | |
| 627 | - s->scscr2 = mem_value; | |
| 628 | - scscr2_changed(s); | |
| 629 | - return; | |
| 630 | - case SH7750_SCFCR2_A7: | |
| 631 | - s->scfcr2 = mem_value; | |
| 632 | - return; | |
| 633 | - case SH7750_SCSMR2_A7: | |
| 634 | - s->scsmr2 = mem_value; | |
| 635 | - return; | |
| 636 | 296 | case SH7750_GPIOIC_A7: |
| 637 | 297 | s->gpioic = mem_value; |
| 638 | 298 | if (mem_value != 0) { |
| ... | ... | @@ -734,7 +394,10 @@ SH7750State *sh7750_init(CPUSH4State * cpu) |
| 734 | 394 | sh7750_mem_read, |
| 735 | 395 | sh7750_mem_write, s); |
| 736 | 396 | cpu_register_physical_memory(0x1c000000, 0x04000000, sh7750_io_memory); |
| 737 | - init_serial_ports(s); | |
| 397 | + | |
| 398 | + sh_serial_init(0x1fe00000, 0, s->periph_freq, serial_hds[0]); | |
| 399 | + sh_serial_init(0x1fe80000, SH_SERIAL_FEAT_SCIF, | |
| 400 | + s->periph_freq, serial_hds[1]); | |
| 738 | 401 | |
| 739 | 402 | tmu012_init(0x1fd80000, |
| 740 | 403 | TMU012_FEAT_TOCR | TMU012_FEAT_3CHAN | TMU012_FEAT_EXTCLK, | ... | ... |
hw/sh7750_regnames.c
| ... | ... | @@ -70,24 +70,6 @@ static regname_t regnames[] = { |
| 70 | 70 | REGNAME(SH7750_CHCR2_A7) |
| 71 | 71 | REGNAME(SH7750_CHCR3_A7) |
| 72 | 72 | REGNAME(SH7750_DMAOR_A7) |
| 73 | - REGNAME(SH7750_SCRDR1_A7) | |
| 74 | - REGNAME(SH7750_SCRDR2_A7) | |
| 75 | - REGNAME(SH7750_SCTDR1_A7) | |
| 76 | - REGNAME(SH7750_SCTDR2_A7) | |
| 77 | - REGNAME(SH7750_SCSMR1_A7) | |
| 78 | - REGNAME(SH7750_SCSMR2_A7) | |
| 79 | - REGNAME(SH7750_SCSCR1_A7) | |
| 80 | - REGNAME(SH7750_SCSCR2_A7) | |
| 81 | - REGNAME(SH7750_SCSSR1_A7) | |
| 82 | - REGNAME(SH7750_SCSFR2_A7) | |
| 83 | - REGNAME(SH7750_SCSPTR1_A7) | |
| 84 | - REGNAME(SH7750_SCSPTR2_A7) | |
| 85 | - REGNAME(SH7750_SCBRR1_A7) | |
| 86 | - REGNAME(SH7750_SCBRR2_A7) | |
| 87 | - REGNAME(SH7750_SCFCR2_A7) | |
| 88 | - REGNAME(SH7750_SCFDR2_A7) | |
| 89 | - REGNAME(SH7750_SCLSR2_A7) | |
| 90 | - REGNAME(SH7750_SCSCMR1_A7) | |
| 91 | 73 | REGNAME(SH7750_PCTRA_A7) |
| 92 | 74 | REGNAME(SH7750_PDTRA_A7) |
| 93 | 75 | REGNAME(SH7750_PCTRB_A7) | ... | ... |
hw/sh7750_regs.h
| ... | ... | @@ -1169,231 +1169,6 @@ |
| 1169 | 1169 | #define SH7750_DMAOR_DME 0x00000001 /* DMAC Master Enable */ |
| 1170 | 1170 | |
| 1171 | 1171 | /* |
| 1172 | - * Serial Communication Interface - SCI | |
| 1173 | - * Serial Communication Interface with FIFO - SCIF | |
| 1174 | - */ | |
| 1175 | -/* SCI Receive Data Register (byte, read-only) - SCRDR1, SCFRDR2 */ | |
| 1176 | -#define SH7750_SCRDR_REGOFS(n) ((n) == 1 ? 0xE00014 : 0xE80014) /* offset */ | |
| 1177 | -#define SH7750_SCRDR(n) SH7750_P4_REG32(SH7750_SCRDR_REGOFS(n)) | |
| 1178 | -#define SH7750_SCRDR1 SH7750_SCRDR(1) | |
| 1179 | -#define SH7750_SCRDR2 SH7750_SCRDR(2) | |
| 1180 | -#define SH7750_SCRDR_A7(n) SH7750_A7_REG32(SH7750_SCRDR_REGOFS(n)) | |
| 1181 | -#define SH7750_SCRDR1_A7 SH7750_SCRDR_A7(1) | |
| 1182 | -#define SH7750_SCRDR2_A7 SH7750_SCRDR_A7(2) | |
| 1183 | - | |
| 1184 | -/* SCI Transmit Data Register (byte) - SCTDR1, SCFTDR2 */ | |
| 1185 | -#define SH7750_SCTDR_REGOFS(n) ((n) == 1 ? 0xE0000C : 0xE8000C) /* offset */ | |
| 1186 | -#define SH7750_SCTDR(n) SH7750_P4_REG32(SH7750_SCTDR_REGOFS(n)) | |
| 1187 | -#define SH7750_SCTDR1 SH7750_SCTDR(1) | |
| 1188 | -#define SH7750_SCTDR2 SH7750_SCTDR(2) | |
| 1189 | -#define SH7750_SCTDR_A7(n) SH7750_A7_REG32(SH7750_SCTDR_REGOFS(n)) | |
| 1190 | -#define SH7750_SCTDR1_A7 SH7750_SCTDR_A7(1) | |
| 1191 | -#define SH7750_SCTDR2_A7 SH7750_SCTDR_A7(2) | |
| 1192 | - | |
| 1193 | -/* SCI Serial Mode Register - SCSMR1(byte), SCSMR2(half) */ | |
| 1194 | -#define SH7750_SCSMR_REGOFS(n) ((n) == 1 ? 0xE00000 : 0xE80000) /* offset */ | |
| 1195 | -#define SH7750_SCSMR(n) SH7750_P4_REG32(SH7750_SCSMR_REGOFS(n)) | |
| 1196 | -#define SH7750_SCSMR1 SH7750_SCSMR(1) | |
| 1197 | -#define SH7750_SCSMR2 SH7750_SCSMR(2) | |
| 1198 | -#define SH7750_SCSMR_A7(n) SH7750_A7_REG32(SH7750_SCSMR_REGOFS(n)) | |
| 1199 | -#define SH7750_SCSMR1_A7 SH7750_SCSMR_A7(1) | |
| 1200 | -#define SH7750_SCSMR2_A7 SH7750_SCSMR_A7(2) | |
| 1201 | - | |
| 1202 | -#define SH7750_SCSMR1_CA 0x80 /* Communication Mode (C/A\): */ | |
| 1203 | -#define SH7750_SCSMR1_CA_ASYNC 0x00 /* Asynchronous Mode */ | |
| 1204 | -#define SH7750_SCSMR1_CA_SYNC 0x80 /* Synchronous Mode */ | |
| 1205 | -#define SH7750_SCSMR_CHR 0x40 /* Character Length: */ | |
| 1206 | -#define SH7750_SCSMR_CHR_8 0x00 /* 8-bit data */ | |
| 1207 | -#define SH7750_SCSMR_CHR_7 0x40 /* 7-bit data */ | |
| 1208 | -#define SH7750_SCSMR_PE 0x20 /* Parity Enable */ | |
| 1209 | -#define SH7750_SCSMR_PM 0x10 /* Parity Mode: */ | |
| 1210 | -#define SH7750_SCSMR_PM_EVEN 0x00 /* Even Parity */ | |
| 1211 | -#define SH7750_SCSMR_PM_ODD 0x10 /* Odd Parity */ | |
| 1212 | -#define SH7750_SCSMR_STOP 0x08 /* Stop Bit Length: */ | |
| 1213 | -#define SH7750_SCSMR_STOP_1 0x00 /* 1 stop bit */ | |
| 1214 | -#define SH7750_SCSMR_STOP_2 0x08 /* 2 stop bit */ | |
| 1215 | -#define SH7750_SCSMR1_MP 0x04 /* Multiprocessor Mode */ | |
| 1216 | -#define SH7750_SCSMR_CKS 0x03 /* Clock Select */ | |
| 1217 | -#define SH7750_SCSMR_CKS_S 0 | |
| 1218 | -#define SH7750_SCSMR_CKS_DIV1 0x00 /* Periph clock */ | |
| 1219 | -#define SH7750_SCSMR_CKS_DIV4 0x01 /* Periph clock / 4 */ | |
| 1220 | -#define SH7750_SCSMR_CKS_DIV16 0x02 /* Periph clock / 16 */ | |
| 1221 | -#define SH7750_SCSMR_CKS_DIV64 0x03 /* Periph clock / 64 */ | |
| 1222 | - | |
| 1223 | -/* SCI Serial Control Register - SCSCR1(byte), SCSCR2(half) */ | |
| 1224 | -#define SH7750_SCSCR_REGOFS(n) ((n) == 1 ? 0xE00008 : 0xE80008) /* offset */ | |
| 1225 | -#define SH7750_SCSCR(n) SH7750_P4_REG32(SH7750_SCSCR_REGOFS(n)) | |
| 1226 | -#define SH7750_SCSCR1 SH7750_SCSCR(1) | |
| 1227 | -#define SH7750_SCSCR2 SH7750_SCSCR(2) | |
| 1228 | -#define SH7750_SCSCR_A7(n) SH7750_A7_REG32(SH7750_SCSCR_REGOFS(n)) | |
| 1229 | -#define SH7750_SCSCR1_A7 SH7750_SCSCR_A7(1) | |
| 1230 | -#define SH7750_SCSCR2_A7 SH7750_SCSCR_A7(2) | |
| 1231 | - | |
| 1232 | -#define SH7750_SCSCR_TIE 0x80 /* Transmit Interrupt Enable */ | |
| 1233 | -#define SH7750_SCSCR_RIE 0x40 /* Receive Interrupt Enable */ | |
| 1234 | -#define SH7750_SCSCR_TE 0x20 /* Transmit Enable */ | |
| 1235 | -#define SH7750_SCSCR_RE 0x10 /* Receive Enable */ | |
| 1236 | -#define SH7750_SCSCR1_MPIE 0x08 /* Multiprocessor Interrupt Enable */ | |
| 1237 | -#define SH7750_SCSCR2_REIE 0x08 /* Receive Error Interrupt Enable */ | |
| 1238 | -#define SH7750_SCSCR1_TEIE 0x04 /* Transmit End Interrupt Enable */ | |
| 1239 | -#define SH7750_SCSCR1_CKE 0x03 /* Clock Enable: */ | |
| 1240 | -#define SH7750_SCSCR_CKE_INTCLK 0x00 /* Use Internal Clock */ | |
| 1241 | -#define SH7750_SCSCR_CKE_EXTCLK 0x02 /* Use External Clock from SCK */ | |
| 1242 | -#define SH7750_SCSCR1_CKE_ASYNC_SCK_CLKOUT 0x01 /* Use SCK as a clock output | |
| 1243 | - in asynchronous mode */ | |
| 1244 | - | |
| 1245 | -/* SCI Serial Status Register - SCSSR1(byte), SCSFR2(half) */ | |
| 1246 | -#define SH7750_SCSSR_REGOFS(n) ((n) == 1 ? 0xE00010 : 0xE80010) /* offset */ | |
| 1247 | -#define SH7750_SCSSR(n) SH7750_P4_REG32(SH7750_SCSSR_REGOFS(n)) | |
| 1248 | -#define SH7750_SCSSR1 SH7750_SCSSR(1) | |
| 1249 | -#define SH7750_SCSFR2 SH7750_SCSSR(2) | |
| 1250 | -#define SH7750_SCSSR_A7(n) SH7750_A7_REG32(SH7750_SCSSR_REGOFS(n)) | |
| 1251 | -#define SH7750_SCSSR1_A7 SH7750_SCSSR_A7(1) | |
| 1252 | -#define SH7750_SCSFR2_A7 SH7750_SCSSR_A7(2) | |
| 1253 | - | |
| 1254 | -#define SH7750_SCSSR1_TDRE 0x80 /* Transmit Data Register Empty */ | |
| 1255 | -#define SH7750_SCSSR1_RDRF 0x40 /* Receive Data Register Full */ | |
| 1256 | -#define SH7750_SCSSR1_ORER 0x20 /* Overrun Error */ | |
| 1257 | -#define SH7750_SCSSR1_FER 0x10 /* Framing Error */ | |
| 1258 | -#define SH7750_SCSSR1_PER 0x08 /* Parity Error */ | |
| 1259 | -#define SH7750_SCSSR1_TEND 0x04 /* Transmit End */ | |
| 1260 | -#define SH7750_SCSSR1_MPB 0x02 /* Multiprocessor Bit */ | |
| 1261 | -#define SH7750_SCSSR1_MPBT 0x01 /* Multiprocessor Bit Transfer */ | |
| 1262 | - | |
| 1263 | -#define SH7750_SCFSR2_PERN 0xF000 /* Number of Parity Errors */ | |
| 1264 | -#define SH7750_SCFSR2_PERN_S 12 | |
| 1265 | -#define SH7750_SCFSR2_FERN 0x0F00 /* Number of Framing Errors */ | |
| 1266 | -#define SH7750_SCFSR2_FERN_S 8 | |
| 1267 | -#define SH7750_SCFSR2_ER 0x0080 /* Receive Error */ | |
| 1268 | -#define SH7750_SCFSR2_TEND 0x0040 /* Transmit End */ | |
| 1269 | -#define SH7750_SCFSR2_TDFE 0x0020 /* Transmit FIFO Data Empty */ | |
| 1270 | -#define SH7750_SCFSR2_BRK 0x0010 /* Break Detect */ | |
| 1271 | -#define SH7750_SCFSR2_FER 0x0008 /* Framing Error */ | |
| 1272 | -#define SH7750_SCFSR2_PER 0x0004 /* Parity Error */ | |
| 1273 | -#define SH7750_SCFSR2_RDF 0x0002 /* Receive FIFO Data Full */ | |
| 1274 | -#define SH7750_SCFSR2_DR 0x0001 /* Receive Data Ready */ | |
| 1275 | - | |
| 1276 | -/* SCI Serial Port Register - SCSPTR1(byte) */ | |
| 1277 | -#define SH7750_SCSPTR1_REGOFS 0xE0001C /* offset */ | |
| 1278 | -#define SH7750_SCSPTR1 SH7750_P4_REG32(SH7750_SCSPTR1_REGOFS) | |
| 1279 | -#define SH7750_SCSPTR1_A7 SH7750_A7_REG32(SH7750_SCSPTR1_REGOFS) | |
| 1280 | - | |
| 1281 | -#define SH7750_SCSPTR1_EIO 0x80 /* Error Interrupt Only */ | |
| 1282 | -#define SH7750_SCSPTR1_SPB1IO 0x08 /* 1: Output SPB1DT bit to SCK pin */ | |
| 1283 | -#define SH7750_SCSPTR1_SPB1DT 0x04 /* Serial Port Clock Port Data */ | |
| 1284 | -#define SH7750_SCSPTR1_SPB0IO 0x02 /* 1: Output SPB0DT bit to TxD pin */ | |
| 1285 | -#define SH7750_SCSPTR1_SPB0DT 0x01 /* Serial Port Break Data */ | |
| 1286 | - | |
| 1287 | -/* SCIF Serial Port Register - SCSPTR2(half) */ | |
| 1288 | -#define SH7750_SCSPTR2_REGOFS 0xE80020 /* offset */ | |
| 1289 | -#define SH7750_SCSPTR2 SH7750_P4_REG32(SH7750_SCSPTR2_REGOFS) | |
| 1290 | -#define SH7750_SCSPTR2_A7 SH7750_A7_REG32(SH7750_SCSPTR2_REGOFS) | |
| 1291 | - | |
| 1292 | -#define SH7750_SCSPTR2_RTSIO 0x80 /* 1: Output RTSDT bit to RTS2\ pin */ | |
| 1293 | -#define SH7750_SCSPTR2_RTSDT 0x40 /* RTS Port Data */ | |
| 1294 | -#define SH7750_SCSPTR2_CTSIO 0x20 /* 1: Output CTSDT bit to CTS2\ pin */ | |
| 1295 | -#define SH7750_SCSPTR2_CTSDT 0x10 /* CTS Port Data */ | |
| 1296 | -#define SH7750_SCSPTR2_SPB2IO 0x02 /* 1: Output SPBDT bit to TxD2 pin */ | |
| 1297 | -#define SH7750_SCSPTR2_SPB2DT 0x01 /* Serial Port Break Data */ | |
| 1298 | - | |
| 1299 | -/* SCI Bit Rate Register - SCBRR1(byte), SCBRR2(byte) */ | |
| 1300 | -#define SH7750_SCBRR_REGOFS(n) ((n) == 1 ? 0xE00004 : 0xE80004) /* offset */ | |
| 1301 | -#define SH7750_SCBRR(n) SH7750_P4_REG32(SH7750_SCBRR_REGOFS(n)) | |
| 1302 | -#define SH7750_SCBRR1 SH7750_SCBRR_P4(1) | |
| 1303 | -#define SH7750_SCBRR2 SH7750_SCBRR_P4(2) | |
| 1304 | -#define SH7750_SCBRR_A7(n) SH7750_A7_REG32(SH7750_SCBRR_REGOFS(n)) | |
| 1305 | -#define SH7750_SCBRR1_A7 SH7750_SCBRR_A7(1) | |
| 1306 | -#define SH7750_SCBRR2_A7 SH7750_SCBRR_A7(2) | |
| 1307 | - | |
| 1308 | -/* SCIF FIFO Control Register - SCFCR2(half) */ | |
| 1309 | -#define SH7750_SCFCR2_REGOFS 0xE80018 /* offset */ | |
| 1310 | -#define SH7750_SCFCR2 SH7750_P4_REG32(SH7750_SCFCR2_REGOFS) | |
| 1311 | -#define SH7750_SCFCR2_A7 SH7750_A7_REG32(SH7750_SCFCR2_REGOFS) | |
| 1312 | - | |
| 1313 | -#define SH7750_SCFCR2_RSTRG 0x700 /* RTS2\ Output Active Trigger; RTS2\ | |
| 1314 | - signal goes to high level when the | |
| 1315 | - number of received data stored in | |
| 1316 | - FIFO exceeds the trigger number */ | |
| 1317 | -#define SH7750_SCFCR2_RSTRG_15 0x000 /* 15 bytes */ | |
| 1318 | -#define SH7750_SCFCR2_RSTRG_1 0x000 /* 1 byte */ | |
| 1319 | -#define SH7750_SCFCR2_RSTRG_4 0x000 /* 4 bytes */ | |
| 1320 | -#define SH7750_SCFCR2_RSTRG_6 0x000 /* 6 bytes */ | |
| 1321 | -#define SH7750_SCFCR2_RSTRG_8 0x000 /* 8 bytes */ | |
| 1322 | -#define SH7750_SCFCR2_RSTRG_10 0x000 /* 10 bytes */ | |
| 1323 | -#define SH7750_SCFCR2_RSTRG_14 0x000 /* 14 bytes */ | |
| 1324 | - | |
| 1325 | -#define SH7750_SCFCR2_RTRG 0x0C0 /* Receive FIFO Data Number Trigger, | |
| 1326 | - Receive Data Full (RDF) Flag sets | |
| 1327 | - when number of receive data bytes is | |
| 1328 | - equal or greater than the trigger | |
| 1329 | - number */ | |
| 1330 | -#define SH7750_SCFCR2_RTRG_1 0x000 /* 1 byte */ | |
| 1331 | -#define SH7750_SCFCR2_RTRG_4 0x040 /* 4 bytes */ | |
| 1332 | -#define SH7750_SCFCR2_RTRG_8 0x080 /* 8 bytes */ | |
| 1333 | -#define SH7750_SCFCR2_RTRG_14 0x0C0 /* 14 bytes */ | |
| 1334 | - | |
| 1335 | -#define SH7750_SCFCR2_TTRG 0x030 /* Transmit FIFO Data Number Trigger, | |
| 1336 | - Transmit FIFO Data Register Empty (TDFE) | |
| 1337 | - flag sets when the number of remaining | |
| 1338 | - transmit data bytes is equal or less | |
| 1339 | - than the trigger number */ | |
| 1340 | -#define SH7750_SCFCR2_TTRG_8 0x000 /* 8 bytes */ | |
| 1341 | -#define SH7750_SCFCR2_TTRG_4 0x010 /* 4 bytes */ | |
| 1342 | -#define SH7750_SCFCR2_TTRG_2 0x020 /* 2 bytes */ | |
| 1343 | -#define SH7750_SCFCR2_TTRG_1 0x030 /* 1 byte */ | |
| 1344 | - | |
| 1345 | -#define SH7750_SCFCR2_MCE 0x008 /* Modem Control Enable */ | |
| 1346 | -#define SH7750_SCFCR2_TFRST 0x004 /* Transmit FIFO Data Register Reset, | |
| 1347 | - invalidates the transmit data in the | |
| 1348 | - transmit FIFO */ | |
| 1349 | -#define SH7750_SCFCR2_RFRST 0x002 /* Receive FIFO Data Register Reset, | |
| 1350 | - invalidates the receive data in the | |
| 1351 | - receive FIFO data register and resets | |
| 1352 | - it to the empty state */ | |
| 1353 | -#define SH7750_SCFCR2_LOOP 0x001 /* Loopback Test */ | |
| 1354 | - | |
| 1355 | -/* SCIF FIFO Data Count Register - SCFDR2(half, read-only) */ | |
| 1356 | -#define SH7750_SCFDR2_REGOFS 0xE8001C /* offset */ | |
| 1357 | -#define SH7750_SCFDR2 SH7750_P4_REG32(SH7750_SCFDR2_REGOFS) | |
| 1358 | -#define SH7750_SCFDR2_A7 SH7750_A7_REG32(SH7750_SCFDR2_REGOFS) | |
| 1359 | - | |
| 1360 | -#define SH7750_SCFDR2_T 0x1F00 /* Number of untransmitted data bytes | |
| 1361 | - in transmit FIFO */ | |
| 1362 | -#define SH7750_SCFDR2_T_S 8 | |
| 1363 | -#define SH7750_SCFDR2_R 0x001F /* Number of received data bytes in | |
| 1364 | - receive FIFO */ | |
| 1365 | -#define SH7750_SCFDR2_R_S 0 | |
| 1366 | - | |
| 1367 | -/* SCIF Line Status Register - SCLSR2(half, read-only) */ | |
| 1368 | -#define SH7750_SCLSR2_REGOFS 0xE80024 /* offset */ | |
| 1369 | -#define SH7750_SCLSR2 SH7750_P4_REG32(SH7750_SCLSR2_REGOFS) | |
| 1370 | -#define SH7750_SCLSR2_A7 SH7750_A7_REG32(SH7750_SCLSR2_REGOFS) | |
| 1371 | - | |
| 1372 | -#define SH7750_SCLSR2_ORER 0x0001 /* Overrun Error */ | |
| 1373 | - | |
| 1374 | -/* | |
| 1375 | - * SCI-based Smart Card Interface | |
| 1376 | - */ | |
| 1377 | -/* Smart Card Mode Register - SCSCMR1(byte) */ | |
| 1378 | -#define SH7750_SCSCMR1_REGOFS 0xE00018 /* offset */ | |
| 1379 | -#define SH7750_SCSCMR1 SH7750_P4_REG32(SH7750_SCSCMR1_REGOFS) | |
| 1380 | -#define SH7750_SCSCMR1_A7 SH7750_A7_REG32(SH7750_SCSCMR1_REGOFS) | |
| 1381 | - | |
| 1382 | -#define SH7750_SCSCMR1_SDIR 0x08 /* Smart Card Data Transfer Direction: */ | |
| 1383 | -#define SH7750_SCSCMR1_SDIR_LSBF 0x00 /* LSB-first */ | |
| 1384 | -#define SH7750_SCSCMR1_SDIR_MSBF 0x08 /* MSB-first */ | |
| 1385 | - | |
| 1386 | -#define SH7750_SCSCMR1_SINV 0x04 /* Smart Card Data Inversion */ | |
| 1387 | -#define SH7750_SCSCMR1_SMIF 0x01 /* Smart Card Interface Mode Select */ | |
| 1388 | - | |
| 1389 | -/* Smart-card specific bits in other registers */ | |
| 1390 | -/* SCSMR1: */ | |
| 1391 | -#define SH7750_SCSMR1_GSM 0x80 /* GSM mode select */ | |
| 1392 | - | |
| 1393 | -/* SCSSR1: */ | |
| 1394 | -#define SH7750_SCSSR1_ERS 0x10 /* Error Signal Status */ | |
| 1395 | - | |
| 1396 | -/* | |
| 1397 | 1172 | * I/O Ports |
| 1398 | 1173 | */ |
| 1399 | 1174 | /* Port Control Register A - PCTRA */ | ... | ... |
hw/sh_serial.c
0 โ 100644
| 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 "vl.h" | |
| 28 | +#include <assert.h> | |
| 29 | + | |
| 30 | +//#define DEBUG_SERIAL | |
| 31 | + | |
| 32 | +#define SH_SERIAL_FLAG_TEND (1 << 0) | |
| 33 | +#define SH_SERIAL_FLAG_TDE (1 << 1) | |
| 34 | +#define SH_SERIAL_FLAG_RDF (1 << 2) | |
| 35 | +#define SH_SERIAL_FLAG_BRK (1 << 3) | |
| 36 | +#define SH_SERIAL_FLAG_DR (1 << 4) | |
| 37 | + | |
| 38 | +typedef struct { | |
| 39 | + uint8_t smr; | |
| 40 | + uint8_t brr; | |
| 41 | + uint8_t scr; | |
| 42 | + uint8_t dr; /* ftdr / tdr */ | |
| 43 | + uint8_t sr; /* fsr / ssr */ | |
| 44 | + uint16_t fcr; | |
| 45 | + uint8_t sptr; | |
| 46 | + | |
| 47 | + uint8_t rx_fifo[16]; /* frdr / rdr */ | |
| 48 | + uint8_t rx_cnt; | |
| 49 | + | |
| 50 | + target_phys_addr_t base; | |
| 51 | + int freq; | |
| 52 | + int feat; | |
| 53 | + int flags; | |
| 54 | + | |
| 55 | + CharDriverState *chr; | |
| 56 | +} sh_serial_state; | |
| 57 | + | |
| 58 | +static void sh_serial_ioport_write(void *opaque, uint32_t offs, uint32_t val) | |
| 59 | +{ | |
| 60 | + sh_serial_state *s = opaque; | |
| 61 | + unsigned char ch; | |
| 62 | + | |
| 63 | +#ifdef DEBUG_SERIAL | |
| 64 | + printf("sh_serial: write base=0x%08lx offs=0x%02x val=0x%02x\n", | |
| 65 | + (unsigned long) s->base, offs, val); | |
| 66 | +#endif | |
| 67 | + switch(offs) { | |
| 68 | + case 0x00: /* SMR */ | |
| 69 | + s->smr = val & ((s->feat & SH_SERIAL_FEAT_SCIF) ? 0x7b : 0xff); | |
| 70 | + return; | |
| 71 | + case 0x04: /* BRR */ | |
| 72 | + s->brr = val; | |
| 73 | + return; | |
| 74 | + case 0x08: /* SCR */ | |
| 75 | + s->scr = val & ((s->feat & SH_SERIAL_FEAT_SCIF) ? 0xfb : 0xff); | |
| 76 | + if (!(val & (1 << 5))) | |
| 77 | + s->flags |= SH_SERIAL_FLAG_TEND; | |
| 78 | + return; | |
| 79 | + case 0x0c: /* FTDR / TDR */ | |
| 80 | + if (s->chr) { | |
| 81 | + ch = val; | |
| 82 | + qemu_chr_write(s->chr, &ch, 1); | |
| 83 | + } | |
| 84 | + s->dr = val; | |
| 85 | + s->flags &= ~SH_SERIAL_FLAG_TDE; | |
| 86 | + return; | |
| 87 | +#if 0 | |
| 88 | + case 0x14: /* FRDR / RDR */ | |
| 89 | + ret = 0; | |
| 90 | + break; | |
| 91 | +#endif | |
| 92 | + } | |
| 93 | + if (s->feat & SH_SERIAL_FEAT_SCIF) { | |
| 94 | + switch(offs) { | |
| 95 | + case 0x10: /* FSR */ | |
| 96 | + if (!(val & (1 << 6))) | |
| 97 | + s->flags &= ~SH_SERIAL_FLAG_TEND; | |
| 98 | + if (!(val & (1 << 5))) | |
| 99 | + s->flags &= ~SH_SERIAL_FLAG_TDE; | |
| 100 | + if (!(val & (1 << 4))) | |
| 101 | + s->flags &= ~SH_SERIAL_FLAG_BRK; | |
| 102 | + if (!(val & (1 << 1))) | |
| 103 | + s->flags &= ~SH_SERIAL_FLAG_RDF; | |
| 104 | + if (!(val & (1 << 0))) | |
| 105 | + s->flags &= ~SH_SERIAL_FLAG_DR; | |
| 106 | + return; | |
| 107 | + case 0x18: /* FCR */ | |
| 108 | + s->fcr = val; | |
| 109 | + return; | |
| 110 | + case 0x20: /* SPTR */ | |
| 111 | + s->sptr = val; | |
| 112 | + return; | |
| 113 | + case 0x24: /* LSR */ | |
| 114 | + return; | |
| 115 | + } | |
| 116 | + } | |
| 117 | + else { | |
| 118 | +#if 0 | |
| 119 | + switch(offs) { | |
| 120 | + case 0x0c: | |
| 121 | + ret = s->dr; | |
| 122 | + break; | |
| 123 | + case 0x10: | |
| 124 | + ret = 0; | |
| 125 | + break; | |
| 126 | + case 0x1c: | |
| 127 | + ret = s->sptr; | |
| 128 | + break; | |
| 129 | + } | |
| 130 | +#endif | |
| 131 | + } | |
| 132 | + | |
| 133 | + fprintf(stderr, "sh_serial: unsupported write to 0x%02x\n", offs); | |
| 134 | + assert(0); | |
| 135 | +} | |
| 136 | + | |
| 137 | +static uint32_t sh_serial_ioport_read(void *opaque, uint32_t offs) | |
| 138 | +{ | |
| 139 | + sh_serial_state *s = opaque; | |
| 140 | + uint32_t ret = ~0; | |
| 141 | + | |
| 142 | +#if 0 | |
| 143 | + switch(offs) { | |
| 144 | + case 0x00: | |
| 145 | + ret = s->smr; | |
| 146 | + break; | |
| 147 | + case 0x04: | |
| 148 | + ret = s->brr; | |
| 149 | + break; | |
| 150 | + case 0x08: | |
| 151 | + ret = s->scr; | |
| 152 | + break; | |
| 153 | + case 0x14: | |
| 154 | + ret = 0; | |
| 155 | + break; | |
| 156 | + } | |
| 157 | +#endif | |
| 158 | + if (s->feat & SH_SERIAL_FEAT_SCIF) { | |
| 159 | + switch(offs) { | |
| 160 | + case 0x10: /* FSR */ | |
| 161 | + ret = 0; | |
| 162 | + if (s->flags & SH_SERIAL_FLAG_TEND) | |
| 163 | + ret |= (1 << 6); | |
| 164 | + if (s->flags & SH_SERIAL_FLAG_TDE) | |
| 165 | + ret |= (1 << 5); | |
| 166 | + if (s->flags & SH_SERIAL_FLAG_BRK) | |
| 167 | + ret |= (1 << 4); | |
| 168 | + if (s->flags & SH_SERIAL_FLAG_RDF) | |
| 169 | + ret |= (1 << 1); | |
| 170 | + if (s->flags & SH_SERIAL_FLAG_DR) | |
| 171 | + ret |= (1 << 0); | |
| 172 | + | |
| 173 | + if (s->scr & (1 << 5)) | |
| 174 | + s->flags |= SH_SERIAL_FLAG_TDE | SH_SERIAL_FLAG_TEND; | |
| 175 | + | |
| 176 | + break; | |
| 177 | +#if 0 | |
| 178 | + case 0x18: | |
| 179 | + ret = s->fcr; | |
| 180 | + break; | |
| 181 | +#endif | |
| 182 | + case 0x1c: | |
| 183 | + ret = s->rx_cnt; | |
| 184 | + break; | |
| 185 | + case 0x20: | |
| 186 | + ret = s->sptr; | |
| 187 | + break; | |
| 188 | + case 0x24: | |
| 189 | + ret = 0; | |
| 190 | + break; | |
| 191 | + } | |
| 192 | + } | |
| 193 | + else { | |
| 194 | +#if 0 | |
| 195 | + switch(offs) { | |
| 196 | + case 0x0c: | |
| 197 | + ret = s->dr; | |
| 198 | + break; | |
| 199 | + case 0x10: | |
| 200 | + ret = 0; | |
| 201 | + break; | |
| 202 | + case 0x1c: | |
| 203 | + ret = s->sptr; | |
| 204 | + break; | |
| 205 | + } | |
| 206 | +#endif | |
| 207 | + } | |
| 208 | +#ifdef DEBUG_SERIAL | |
| 209 | + printf("sh_serial: read base=0x%08lx offs=0x%02x val=0x%x\n", | |
| 210 | + (unsigned long) s->base, offs, ret); | |
| 211 | +#endif | |
| 212 | + | |
| 213 | + if (ret & ~((1 << 16) - 1)) { | |
| 214 | + fprintf(stderr, "sh_serial: unsupported read from 0x%02x\n", offs); | |
| 215 | + assert(0); | |
| 216 | + } | |
| 217 | + | |
| 218 | + return ret; | |
| 219 | +} | |
| 220 | + | |
| 221 | +static int sh_serial_can_receive(sh_serial_state *s) | |
| 222 | +{ | |
| 223 | + return 0; | |
| 224 | +} | |
| 225 | + | |
| 226 | +static void sh_serial_receive_byte(sh_serial_state *s, int ch) | |
| 227 | +{ | |
| 228 | +} | |
| 229 | + | |
| 230 | +static void sh_serial_receive_break(sh_serial_state *s) | |
| 231 | +{ | |
| 232 | +} | |
| 233 | + | |
| 234 | +static int sh_serial_can_receive1(void *opaque) | |
| 235 | +{ | |
| 236 | + sh_serial_state *s = opaque; | |
| 237 | + return sh_serial_can_receive(s); | |
| 238 | +} | |
| 239 | + | |
| 240 | +static void sh_serial_receive1(void *opaque, const uint8_t *buf, int size) | |
| 241 | +{ | |
| 242 | + sh_serial_state *s = opaque; | |
| 243 | + sh_serial_receive_byte(s, buf[0]); | |
| 244 | +} | |
| 245 | + | |
| 246 | +static void sh_serial_event(void *opaque, int event) | |
| 247 | +{ | |
| 248 | + sh_serial_state *s = opaque; | |
| 249 | + if (event == CHR_EVENT_BREAK) | |
| 250 | + sh_serial_receive_break(s); | |
| 251 | +} | |
| 252 | + | |
| 253 | +uint32_t sh_serial_read (void *opaque, target_phys_addr_t addr) | |
| 254 | +{ | |
| 255 | + sh_serial_state *s = opaque; | |
| 256 | + return sh_serial_ioport_read(s, addr - s->base); | |
| 257 | +} | |
| 258 | + | |
| 259 | +void sh_serial_write (void *opaque, | |
| 260 | + target_phys_addr_t addr, uint32_t value) | |
| 261 | +{ | |
| 262 | + sh_serial_state *s = opaque; | |
| 263 | + sh_serial_ioport_write(s, addr - s->base, value); | |
| 264 | +} | |
| 265 | + | |
| 266 | +static CPUReadMemoryFunc *sh_serial_readfn[] = { | |
| 267 | + &sh_serial_read, | |
| 268 | + &sh_serial_read, | |
| 269 | + &sh_serial_read, | |
| 270 | +}; | |
| 271 | + | |
| 272 | +static CPUWriteMemoryFunc *sh_serial_writefn[] = { | |
| 273 | + &sh_serial_write, | |
| 274 | + &sh_serial_write, | |
| 275 | + &sh_serial_write, | |
| 276 | +}; | |
| 277 | + | |
| 278 | +void sh_serial_init (target_phys_addr_t base, int feat, | |
| 279 | + uint32_t freq, CharDriverState *chr) | |
| 280 | +{ | |
| 281 | + sh_serial_state *s; | |
| 282 | + int s_io_memory; | |
| 283 | + | |
| 284 | + s = qemu_mallocz(sizeof(sh_serial_state)); | |
| 285 | + if (!s) | |
| 286 | + return; | |
| 287 | + | |
| 288 | + s->base = base; | |
| 289 | + s->feat = feat; | |
| 290 | + s->flags = SH_SERIAL_FLAG_TEND | SH_SERIAL_FLAG_TDE; | |
| 291 | + | |
| 292 | + s->smr = 0; | |
| 293 | + s->brr = 0xff; | |
| 294 | + s->scr = 0; | |
| 295 | + s->sptr = 0; | |
| 296 | + | |
| 297 | + if (feat & SH_SERIAL_FEAT_SCIF) { | |
| 298 | + s->fcr = 0; | |
| 299 | + } | |
| 300 | + else { | |
| 301 | + s->dr = 0xff; | |
| 302 | + } | |
| 303 | + | |
| 304 | + s->rx_cnt = 0; | |
| 305 | + | |
| 306 | + s_io_memory = cpu_register_io_memory(0, sh_serial_readfn, | |
| 307 | + sh_serial_writefn, s); | |
| 308 | + cpu_register_physical_memory(base, 0x28, s_io_memory); | |
| 309 | + | |
| 310 | + s->chr = chr; | |
| 311 | + | |
| 312 | + if (chr) | |
| 313 | + qemu_chr_add_handlers(chr, sh_serial_can_receive1, sh_serial_receive1, | |
| 314 | + sh_serial_event, s); | |
| 315 | +} | ... | ... |
vl.h
| ... | ... | @@ -1523,6 +1523,11 @@ int sh7750_register_io_device(struct SH7750State *s, |
| 1523 | 1523 | #define TMU012_FEAT_EXTCLK (1 << 2) |
| 1524 | 1524 | void tmu012_init(uint32_t base, int feat, uint32_t freq); |
| 1525 | 1525 | |
| 1526 | +/* sh_serial.c */ | |
| 1527 | +#define SH_SERIAL_FEAT_SCIF (1 << 0) | |
| 1528 | +void sh_serial_init (target_phys_addr_t base, int feat, | |
| 1529 | + uint32_t freq, CharDriverState *chr); | |
| 1530 | + | |
| 1526 | 1531 | /* tc58128.c */ |
| 1527 | 1532 | int tc58128_init(struct SH7750State *s, char *zone1, char *zone2); |
| 1528 | 1533 | ... | ... |