Automatic Copyright Year update after running gdb/copyright.py
[deliverable/binutils-gdb.git] / sim / m68hc11 / dv-m68hc11sio.c
1 /* dv-m68hc11sio.c -- Simulation of the 68HC11 serial device.
2 Copyright (C) 1999-2022 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 unsigned8 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 base = 0;
425 sim_cpu *cpu;
426 struct m68hc11sio *controller;
427 uint8 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 signed64 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 signed64 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 unsigned8 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 *((unsigned8*) 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 unsigned8 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 unsigned8*) 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
This page took 0.043207 seconds and 4 git commands to generate.