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