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