]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - sim/m68hc11/dv-m68hc11sio.c
Update years in copyright notice for the GDB files.
[thirdparty/binutils-gdb.git] / sim / m68hc11 / dv-m68hc11sio.c
1 /* dv-m68hc11sio.c -- Simulation of the 68HC11 serial device.
2 Copyright (C) 1999-2013 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
64 enum
65 {
66 RESET_PORT
67 };
68
69
70 static const struct hw_port_descriptor m68hc11sio_ports[] =
71 {
72 { "reset", RESET_PORT, 0, input_port, },
73 { NULL, },
74 };
75
76
77 /* Serial Controller information. */
78 struct 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
107 static hw_io_read_buffer_method m68hc11sio_io_read_buffer;
108 static hw_io_write_buffer_method m68hc11sio_io_write_buffer;
109 static hw_port_event_method m68hc11sio_port_event;
110 static hw_ioctl_method m68hc11sio_ioctl;
111
112 #define M6811_SCI_FIRST_REG (M6811_BAUD)
113 #define M6811_SCI_LAST_REG (M6811_SCDR)
114
115
116 static void
117 attach_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
139 static void
140 m68hc11sio_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
175 static void
176 m68hc11sio_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
243 void
244 m68hc11sio_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
316 void
317 m68hc11sio_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. */
376 io_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
388 io_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
396 io_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
407 io_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
418 static void
419 m68hc11sio_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
479 static int
480 m68hc11sio_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
490 static unsigned
491 m68hc11sio_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
535 static unsigned
536 m68hc11sio_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
656 const struct hw_descriptor dv_m68hc11sio_descriptor[] = {
657 { "m68hc11sio", m68hc11sio_finish },
658 { "m68hc12sio", m68hc11sio_finish },
659 { NULL },
660 };
661