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