1 /* dv-m68hc11sio.c -- Simulation of the 68HC11 serial device. 2 Copyright (C) 1999-2024 Free Software Foundation, Inc. 3 Written by Stephane Carrez (stcarrez@worldnet.fr) 4 (From a driver model Contributed by Cygnus Solutions.) 5 6 This file is part of the program GDB, the GNU debugger. 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program. If not, see <http://www.gnu.org/licenses/>. 20 21 */ 22 23 /* This must come before any other includes. */ 24 #include "defs.h" 25 26 #include "sim-main.h" 27 #include "hw-main.h" 28 #include "dv-sockser.h" 29 #include "sim-assert.h" 30 31 #include "m68hc11-sim.h" 32 33 /* DEVICE 34 35 m68hc11sio - m68hc11 serial I/O 36 37 38 DESCRIPTION 39 40 Implements the m68hc11 serial I/O controller described in the m68hc11 41 user guide. The serial I/O controller is directly connected to the CPU 42 interrupt. The simulator implements: 43 44 - baud rate emulation 45 - 8-bits transfers 46 47 PROPERTIES 48 49 backend {tcp | stdio} 50 51 Use dv-sockser TCP-port backend or stdio for backend. Default: stdio. 52 53 54 PORTS 55 56 reset (input) 57 58 Reset port. This port is only used to simulate a reset of the serial 59 I/O controller. It should be connected to the RESET output of the cpu. 60 61 */ 62 63 64 65 /* port ID's */ 66 67 enum 68 { 69 RESET_PORT 70 }; 71 72 73 static const struct hw_port_descriptor m68hc11sio_ports[] = 74 { 75 { "reset", RESET_PORT, 0, input_port, }, 76 { NULL, }, 77 }; 78 79 80 /* Serial Controller information. */ 81 struct m68hc11sio 82 { 83 enum {sio_tcp, sio_stdio} backend; /* backend */ 84 85 /* Number of cpu cycles to send a bit on the wire. */ 86 unsigned long baud_cycle; 87 88 /* Length in bits of characters sent, this includes the 89 start/stop and parity bits. Together with baud_cycle, this 90 is used to find the number of cpu cycles to send/receive a data. */ 91 unsigned int data_length; 92 93 /* Information about next character to be transmited. */ 94 unsigned char tx_has_char; 95 unsigned char tx_char; 96 97 unsigned char rx_char; 98 unsigned char rx_clear_scsr; 99 100 /* Periodic I/O polling. */ 101 struct hw_event* tx_poll_event; 102 struct hw_event* rx_poll_event; 103 }; 104 105 106 107 /* Finish off the partially created hw device. Attach our local 108 callbacks. Wire up our port names etc. */ 109 110 static hw_io_read_buffer_method m68hc11sio_io_read_buffer; 111 static hw_io_write_buffer_method m68hc11sio_io_write_buffer; 112 static hw_port_event_method m68hc11sio_port_event; 113 static hw_ioctl_method m68hc11sio_ioctl; 114 115 #define M6811_SCI_FIRST_REG (M6811_BAUD) 116 #define M6811_SCI_LAST_REG (M6811_SCDR) 117 118 119 static void 120 attach_m68hc11sio_regs (struct hw *me, 121 struct m68hc11sio *controller) 122 { 123 hw_attach_address (hw_parent (me), M6811_IO_LEVEL, io_map, 124 M6811_SCI_FIRST_REG, 125 M6811_SCI_LAST_REG - M6811_SCI_FIRST_REG + 1, 126 me); 127 128 if (hw_find_property(me, "backend") != NULL) 129 { 130 const char *value = hw_find_string_property(me, "backend"); 131 if(! strcmp(value, "tcp")) 132 controller->backend = sio_tcp; 133 else if(! strcmp(value, "stdio")) 134 controller->backend = sio_stdio; 135 else 136 hw_abort (me, "illegal value for backend parameter `%s':" 137 "use tcp or stdio", value); 138 } 139 } 140 141 142 static void 143 m68hc11sio_finish (struct hw *me) 144 { 145 struct m68hc11sio *controller; 146 147 controller = HW_ZALLOC (me, struct m68hc11sio); 148 set_hw_data (me, controller); 149 set_hw_io_read_buffer (me, m68hc11sio_io_read_buffer); 150 set_hw_io_write_buffer (me, m68hc11sio_io_write_buffer); 151 set_hw_ports (me, m68hc11sio_ports); 152 set_hw_port_event (me, m68hc11sio_port_event); 153 #ifdef set_hw_ioctl 154 set_hw_ioctl (me, m68hc11sio_ioctl); 155 #else 156 me->to_ioctl = m68hc11sio_ioctl; 157 #endif 158 159 /* Preset defaults. */ 160 controller->backend = sio_stdio; 161 162 /* Attach ourself to our parent bus. */ 163 attach_m68hc11sio_regs (me, controller); 164 165 /* Initialize to reset state. */ 166 controller->tx_poll_event = NULL; 167 controller->rx_poll_event = NULL; 168 controller->tx_char = 0; 169 controller->tx_has_char = 0; 170 controller->rx_clear_scsr = 0; 171 controller->rx_char = 0; 172 } 173 174 175 176 /* An event arrives on an interrupt port. */ 177 178 static void 179 m68hc11sio_port_event (struct hw *me, 180 int my_port, 181 struct hw *source, 182 int source_port, 183 int level) 184 { 185 SIM_DESC sd; 186 struct m68hc11sio *controller; 187 sim_cpu *cpu; 188 struct m68hc11_sim_cpu *m68hc11_cpu; 189 uint8_t val; 190 191 controller = hw_data (me); 192 sd = hw_system (me); 193 cpu = STATE_CPU (sd, 0); 194 m68hc11_cpu = M68HC11_SIM_CPU (cpu); 195 switch (my_port) 196 { 197 case RESET_PORT: 198 { 199 HW_TRACE ((me, "SCI reset")); 200 201 /* Reset the state of SCI registers. */ 202 val = 0; 203 m68hc11sio_io_write_buffer (me, &val, io_map, 204 (unsigned_word) M6811_BAUD, 1); 205 m68hc11sio_io_write_buffer (me, &val, io_map, 206 (unsigned_word) M6811_SCCR1, 1); 207 m68hc11sio_io_write_buffer (me, &val, io_map, 208 (unsigned_word) M6811_SCCR2, 1); 209 210 m68hc11_cpu->ios[M6811_SCSR] = M6811_TC | M6811_TDRE; 211 controller->rx_char = 0; 212 controller->tx_char = 0; 213 controller->tx_has_char = 0; 214 controller->rx_clear_scsr = 0; 215 if (controller->rx_poll_event) 216 { 217 hw_event_queue_deschedule (me, controller->rx_poll_event); 218 controller->rx_poll_event = 0; 219 } 220 if (controller->tx_poll_event) 221 { 222 hw_event_queue_deschedule (me, controller->tx_poll_event); 223 controller->tx_poll_event = 0; 224 } 225 226 /* In bootstrap mode, initialize the SCI to 1200 bauds to 227 simulate some initial setup by the internal rom. */ 228 if (((m68hc11_cpu->ios[M6811_HPRIO]) & (M6811_SMOD | M6811_MDA)) == M6811_SMOD) 229 { 230 val = 0x33; 231 232 m68hc11sio_io_write_buffer (me, &val, io_map, 233 (unsigned_word) M6811_BAUD, 1); 234 val = 0x12; 235 m68hc11sio_io_write_buffer (me, &val, io_map, 236 (unsigned_word) M6811_SCCR2, 1); 237 } 238 break; 239 } 240 241 default: 242 hw_abort (me, "Event on unknown port %d", my_port); 243 break; 244 } 245 } 246 247 248 static void 249 m68hc11sio_rx_poll (struct hw *me, void *data) 250 { 251 SIM_DESC sd; 252 struct m68hc11sio *controller; 253 sim_cpu *cpu; 254 struct m68hc11_sim_cpu *m68hc11_cpu; 255 char cc; 256 int cnt; 257 int check_interrupt = 0; 258 259 controller = hw_data (me); 260 sd = hw_system (me); 261 cpu = STATE_CPU (sd, 0); 262 m68hc11_cpu = M68HC11_SIM_CPU (cpu); 263 switch (controller->backend) 264 { 265 case sio_tcp: 266 cnt = dv_sockser_read (sd); 267 if (cnt != -1) 268 { 269 cc = (char) cnt; 270 cnt = 1; 271 } 272 break; 273 274 case sio_stdio: 275 cnt = sim_io_poll_read (sd, 0 /* stdin */, &cc, 1); 276 break; 277 278 default: 279 cnt = 0; 280 break; 281 } 282 283 if (cnt == 1) 284 { 285 /* Raise the overrun flag if the previous character was not read. */ 286 if (m68hc11_cpu->ios[M6811_SCSR] & M6811_RDRF) 287 m68hc11_cpu->ios[M6811_SCSR] |= M6811_OR; 288 289 m68hc11_cpu->ios[M6811_SCSR] |= M6811_RDRF; 290 controller->rx_char = cc; 291 controller->rx_clear_scsr = 0; 292 check_interrupt = 1; 293 } 294 else 295 { 296 /* handle idle line detect here. */ 297 ; 298 } 299 300 if (controller->rx_poll_event) 301 { 302 hw_event_queue_deschedule (me, controller->rx_poll_event); 303 controller->rx_poll_event = 0; 304 } 305 306 if (m68hc11_cpu->ios[M6811_SCCR2] & M6811_RE) 307 { 308 unsigned long clock_cycle; 309 310 /* Compute CPU clock cycles to wait for the next character. */ 311 clock_cycle = controller->data_length * controller->baud_cycle; 312 313 controller->rx_poll_event = hw_event_queue_schedule (me, clock_cycle, 314 m68hc11sio_rx_poll, 315 NULL); 316 } 317 318 if (check_interrupt) 319 interrupts_update_pending (&m68hc11_cpu->cpu_interrupts); 320 } 321 322 323 static void 324 m68hc11sio_tx_poll (struct hw *me, void *data) 325 { 326 SIM_DESC sd; 327 struct m68hc11sio *controller; 328 sim_cpu *cpu; 329 struct m68hc11_sim_cpu *m68hc11_cpu; 330 331 controller = hw_data (me); 332 sd = hw_system (me); 333 cpu = STATE_CPU (sd, 0); 334 m68hc11_cpu = M68HC11_SIM_CPU (cpu); 335 336 m68hc11_cpu->ios[M6811_SCSR] |= M6811_TDRE; 337 m68hc11_cpu->ios[M6811_SCSR] |= M6811_TC; 338 339 /* Transmitter is enabled and we have something to send. */ 340 if ((m68hc11_cpu->ios[M6811_SCCR2] & M6811_TE) && controller->tx_has_char) 341 { 342 m68hc11_cpu->ios[M6811_SCSR] &= ~M6811_TDRE; 343 m68hc11_cpu->ios[M6811_SCSR] &= ~M6811_TC; 344 controller->tx_has_char = 0; 345 switch (controller->backend) 346 { 347 case sio_tcp: 348 dv_sockser_write (sd, controller->tx_char); 349 break; 350 351 case sio_stdio: 352 sim_io_write_stdout (sd, (const char *)&controller->tx_char, 1); 353 sim_io_flush_stdout (sd); 354 break; 355 356 default: 357 break; 358 } 359 } 360 361 if (controller->tx_poll_event) 362 { 363 hw_event_queue_deschedule (me, controller->tx_poll_event); 364 controller->tx_poll_event = 0; 365 } 366 367 if ((m68hc11_cpu->ios[M6811_SCCR2] & M6811_TE) 368 && ((m68hc11_cpu->ios[M6811_SCSR] & M6811_TC) == 0)) 369 { 370 unsigned long clock_cycle; 371 372 /* Compute CPU clock cycles to wait for the next character. */ 373 clock_cycle = controller->data_length * controller->baud_cycle; 374 375 controller->tx_poll_event = hw_event_queue_schedule (me, clock_cycle, 376 m68hc11sio_tx_poll, 377 NULL); 378 } 379 380 interrupts_update_pending (&m68hc11_cpu->cpu_interrupts); 381 } 382 383 /* Descriptions of the SIO I/O ports. These descriptions are only used to 384 give information of the SIO device under GDB. */ 385 io_reg_desc sccr2_desc[] = { 386 { M6811_TIE, "TIE ", "Transmit Interrupt Enable" }, 387 { M6811_TCIE, "TCIE ", "Transmit Complete Interrupt Enable" }, 388 { M6811_RIE, "RIE ", "Receive Interrupt Enable" }, 389 { M6811_ILIE, "ILIE ", "Idle Line Interrupt Enable" }, 390 { M6811_TE, "TE ", "Transmit Enable" }, 391 { M6811_RE, "RE ", "Receive Enable" }, 392 { M6811_RWU, "RWU ", "Receiver Wake Up" }, 393 { M6811_SBK, "SBRK ", "Send Break" }, 394 { 0, 0, 0 } 395 }; 396 397 io_reg_desc sccr1_desc[] = { 398 { M6811_R8, "R8 ", "Receive Data bit 8" }, 399 { M6811_T8, "T8 ", "Transmit Data bit 8" }, 400 { M6811_M, "M ", "SCI Character length (0=8-bits, 1=9-bits)" }, 401 { M6811_WAKE, "WAKE ", "Wake up method select (0=idle, 1=addr mark" }, 402 { 0, 0, 0 } 403 }; 404 405 io_reg_desc scsr_desc[] = { 406 { M6811_TDRE, "TDRE ", "Transmit Data Register Empty" }, 407 { M6811_TC, "TC ", "Transmit Complete" }, 408 { M6811_RDRF, "RDRF ", "Receive Data Register Full" }, 409 { M6811_IDLE, "IDLE ", "Idle Line Detect" }, 410 { M6811_OR, "OR ", "Overrun Error" }, 411 { M6811_NF, "NF ", "Noise Flag" }, 412 { M6811_FE, "FE ", "Framing Error" }, 413 { 0, 0, 0 } 414 }; 415 416 io_reg_desc baud_desc[] = { 417 { M6811_TCLR, "TCLR ", "Clear baud rate (test mode)" }, 418 { M6811_SCP1, "SCP1 ", "SCI baud rate prescaler select (SCP1)" }, 419 { M6811_SCP0, "SCP0 ", "SCI baud rate prescaler select (SCP0)" }, 420 { M6811_RCKB, "RCKB ", "Baur Rate Clock Check (test mode)" }, 421 { M6811_SCR2, "SCR2 ", "SCI Baud rate select (SCR2)" }, 422 { M6811_SCR1, "SCR1 ", "SCI Baud rate select (SCR1)" }, 423 { M6811_SCR0, "SCR0 ", "SCI Baud rate select (SCR0)" }, 424 { 0, 0, 0 } 425 }; 426 427 static void 428 m68hc11sio_info (struct hw *me) 429 { 430 SIM_DESC sd; 431 uint16_t base = 0; 432 sim_cpu *cpu; 433 struct m68hc11_sim_cpu *m68hc11_cpu; 434 struct m68hc11sio *controller; 435 uint8_t val; 436 long clock_cycle; 437 438 sd = hw_system (me); 439 cpu = STATE_CPU (sd, 0); 440 m68hc11_cpu = M68HC11_SIM_CPU (cpu); 441 controller = hw_data (me); 442 443 sim_io_printf (sd, "M68HC11 SIO:\n"); 444 445 base = cpu_get_io_base (cpu); 446 447 val = m68hc11_cpu->ios[M6811_BAUD]; 448 print_io_byte (sd, "BAUD ", baud_desc, val, base + M6811_BAUD); 449 sim_io_printf (sd, " (%ld baud)\n", 450 (m68hc11_cpu->cpu_frequency / 4) / controller->baud_cycle); 451 452 val = m68hc11_cpu->ios[M6811_SCCR1]; 453 print_io_byte (sd, "SCCR1", sccr1_desc, val, base + M6811_SCCR1); 454 sim_io_printf (sd, " (%d bits) (%dN1)\n", 455 controller->data_length, controller->data_length - 2); 456 457 val = m68hc11_cpu->ios[M6811_SCCR2]; 458 print_io_byte (sd, "SCCR2", sccr2_desc, val, base + M6811_SCCR2); 459 sim_io_printf (sd, "\n"); 460 461 val = m68hc11_cpu->ios[M6811_SCSR]; 462 print_io_byte (sd, "SCSR ", scsr_desc, val, base + M6811_SCSR); 463 sim_io_printf (sd, "\n"); 464 465 clock_cycle = controller->data_length * controller->baud_cycle; 466 467 if (controller->tx_poll_event) 468 { 469 int64_t t; 470 int n; 471 472 t = hw_event_remain_time (me, controller->tx_poll_event); 473 n = (clock_cycle - t) / controller->baud_cycle; 474 n = controller->data_length - n; 475 sim_io_printf (sd, " Transmit finished in %s (%d bit%s)\n", 476 cycle_to_string (cpu, t, PRINT_TIME | PRINT_CYCLE), 477 n, (n > 1 ? "s" : "")); 478 } 479 if (controller->rx_poll_event) 480 { 481 int64_t t; 482 483 t = hw_event_remain_time (me, controller->rx_poll_event); 484 sim_io_printf (sd, " Receive finished in %s\n", 485 cycle_to_string (cpu, t, PRINT_TIME | PRINT_CYCLE)); 486 } 487 488 } 489 490 static int 491 m68hc11sio_ioctl (struct hw *me, 492 hw_ioctl_request request, 493 va_list ap) 494 { 495 m68hc11sio_info (me); 496 return 0; 497 } 498 499 /* generic read/write */ 500 501 static unsigned 502 m68hc11sio_io_read_buffer (struct hw *me, 503 void *dest, 504 int space, 505 unsigned_word base, 506 unsigned nr_bytes) 507 { 508 SIM_DESC sd; 509 struct m68hc11sio *controller; 510 sim_cpu *cpu; 511 struct m68hc11_sim_cpu *m68hc11_cpu; 512 uint8_t val; 513 514 HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes)); 515 516 sd = hw_system (me); 517 cpu = STATE_CPU (sd, 0); 518 m68hc11_cpu = M68HC11_SIM_CPU (cpu); 519 controller = hw_data (me); 520 521 switch (base) 522 { 523 case M6811_SCSR: 524 controller->rx_clear_scsr = m68hc11_cpu->ios[M6811_SCSR] 525 & (M6811_RDRF | M6811_IDLE | M6811_OR | M6811_NF | M6811_FE); 526 ATTRIBUTE_FALLTHROUGH; 527 528 case M6811_BAUD: 529 case M6811_SCCR1: 530 case M6811_SCCR2: 531 val = m68hc11_cpu->ios[base]; 532 break; 533 534 case M6811_SCDR: 535 if (controller->rx_clear_scsr) 536 { 537 m68hc11_cpu->ios[M6811_SCSR] &= ~controller->rx_clear_scsr; 538 } 539 val = controller->rx_char; 540 break; 541 542 default: 543 return 0; 544 } 545 *((uint8_t*) dest) = val; 546 return 1; 547 } 548 549 static unsigned 550 m68hc11sio_io_write_buffer (struct hw *me, 551 const void *source, 552 int space, 553 unsigned_word base, 554 unsigned nr_bytes) 555 { 556 SIM_DESC sd; 557 struct m68hc11sio *controller; 558 sim_cpu *cpu; 559 struct m68hc11_sim_cpu *m68hc11_cpu; 560 uint8_t val; 561 562 HW_TRACE ((me, "write 0x%08lx %d", (long) base, (int) nr_bytes)); 563 564 sd = hw_system (me); 565 cpu = STATE_CPU (sd, 0); 566 m68hc11_cpu = M68HC11_SIM_CPU (cpu); 567 controller = hw_data (me); 568 569 val = *((const uint8_t*) source); 570 switch (base) 571 { 572 case M6811_BAUD: 573 { 574 long divisor; 575 long baud; 576 577 m68hc11_cpu->ios[M6811_BAUD] = val; 578 switch (val & (M6811_SCP1|M6811_SCP0)) 579 { 580 case M6811_BAUD_DIV_1: 581 divisor = 1 * 16; 582 break; 583 584 case M6811_BAUD_DIV_3: 585 divisor = 3 * 16; 586 break; 587 588 case M6811_BAUD_DIV_4: 589 divisor = 4 * 16; 590 break; 591 592 default: 593 case M6811_BAUD_DIV_13: 594 divisor = 13 * 16; 595 break; 596 } 597 val &= (M6811_SCR2|M6811_SCR1|M6811_SCR0); 598 divisor *= (1 << val); 599 600 baud = (m68hc11_cpu->cpu_frequency / 4) / divisor; 601 602 HW_TRACE ((me, "divide rate %ld, baud rate %ld", 603 divisor, baud)); 604 605 controller->baud_cycle = divisor; 606 } 607 break; 608 609 case M6811_SCCR1: 610 { 611 if (val & M6811_M) 612 controller->data_length = 11; 613 else 614 controller->data_length = 10; 615 616 m68hc11_cpu->ios[M6811_SCCR1] = val; 617 } 618 break; 619 620 case M6811_SCCR2: 621 if ((val & M6811_RE) == 0) 622 { 623 val &= ~(M6811_RDRF|M6811_IDLE|M6811_OR|M6811_NF|M6811_NF); 624 val |= (m68hc11_cpu->ios[M6811_SCCR2] 625 & (M6811_RDRF|M6811_IDLE|M6811_OR|M6811_NF|M6811_NF)); 626 m68hc11_cpu->ios[M6811_SCCR2] = val; 627 break; 628 } 629 630 /* Activate reception. */ 631 if (controller->rx_poll_event == 0) 632 { 633 long clock_cycle; 634 635 /* Compute CPU clock cycles to wait for the next character. */ 636 clock_cycle = controller->data_length * controller->baud_cycle; 637 638 controller->rx_poll_event = hw_event_queue_schedule (me, clock_cycle, 639 m68hc11sio_rx_poll, 640 NULL); 641 } 642 m68hc11_cpu->ios[M6811_SCCR2] = val; 643 interrupts_update_pending (&m68hc11_cpu->cpu_interrupts); 644 break; 645 646 /* No effect. */ 647 case M6811_SCSR: 648 return 1; 649 650 case M6811_SCDR: 651 if (!(m68hc11_cpu->ios[M6811_SCSR] & M6811_TDRE)) 652 { 653 return 0; 654 } 655 656 controller->tx_char = val; 657 controller->tx_has_char = 1; 658 if ((m68hc11_cpu->ios[M6811_SCCR2] & M6811_TE) 659 && controller->tx_poll_event == 0) 660 { 661 m68hc11sio_tx_poll (me, NULL); 662 } 663 return 1; 664 665 default: 666 return 0; 667 } 668 return nr_bytes; 669 } 670 671 672 const struct hw_descriptor dv_m68hc11sio_descriptor[] = { 673 { "m68hc11sio", m68hc11sio_finish }, 674 { "m68hc12sio", m68hc11sio_finish }, 675 { NULL }, 676 }; 677 678