New simulator.
[deliverable/binutils-gdb.git] / sim / m68hc11 / dv-m68hc11sio.c
1 /* dv-m68hc11sio.c -- Simulation of the 68HC11 serial device.
2 Copyright (C) 1999, 2000 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 2 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, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
22 */
23
24
25 #include "sim-main.h"
26 #include "hw-main.h"
27 #include "dv-sockser.h"
28 #include "sim-assert.h"
29
30
31 /* DEVICE
32
33 m68hc11sio - m68hc11 serial I/O
34
35
36 DESCRIPTION
37
38 Implements the m68hc11 serial I/O controller described in the m68hc11
39 user guide. The serial I/O controller is directly connected to the CPU
40 interrupt. The simulator implements:
41
42 - baud rate emulation
43 - 8-bits transfers
44
45 PROPERTIES
46
47 backend {tcp | stdio}
48
49 Use dv-sockser TCP-port backend or stdio for backend. Default: stdio.
50
51
52 PORTS
53
54 reset (input)
55
56 Reset port. This port is only used to simulate a reset of the serial
57 I/O controller. It should be connected to the RESET output of the cpu.
58
59 */
60
61
62
63 /* port ID's */
64
65 enum
66 {
67 RESET_PORT
68 };
69
70
71 static const struct hw_port_descriptor m68hc11sio_ports[] =
72 {
73 { "reset", RESET_PORT, 0, input_port, },
74 { NULL, },
75 };
76
77
78 /* Serial Controller information. */
79 struct m68hc11sio
80 {
81 enum {sio_tcp, sio_stdio} backend; /* backend */
82
83 /* Number of cpu cycles to send a bit on the wire. */
84 unsigned long baud_cycle;
85
86 /* Length in bits of characters sent, this includes the
87 start/stop and parity bits. Together with baud_cycle, this
88 is used to find the number of cpu cycles to send/receive a data. */
89 unsigned int data_length;
90
91 /* Information about next character to be transmited. */
92 unsigned char tx_has_char;
93 unsigned char tx_char;
94
95 unsigned char rx_char;
96 unsigned char rx_clear_scsr;
97
98 /* Periodic I/O polling. */
99 struct hw_event* tx_poll_event;
100 struct hw_event* rx_poll_event;
101 };
102
103
104
105 /* Finish off the partially created hw device. Attach our local
106 callbacks. Wire up our port names etc. */
107
108 static hw_io_read_buffer_method m68hc11sio_io_read_buffer;
109 static hw_io_write_buffer_method m68hc11sio_io_write_buffer;
110 static hw_port_event_method m68hc11sio_port_event;
111 static hw_ioctl_method m68hc11sio_ioctl;
112
113 #define M6811_SCI_FIRST_REG (M6811_BAUD)
114 #define M6811_SCI_LAST_REG (M6811_SCDR)
115
116
117 static void
118 attach_m68hc11sio_regs (struct hw *me,
119 struct m68hc11sio *controller)
120 {
121 hw_attach_address (hw_parent (me), 0, io_map,
122 M6811_SCI_FIRST_REG,
123 M6811_SCI_LAST_REG - M6811_SCI_FIRST_REG + 1,
124 me);
125
126 if (hw_find_property(me, "backend") != NULL)
127 {
128 const char *value = hw_find_string_property(me, "backend");
129 if(! strcmp(value, "tcp"))
130 controller->backend = sio_tcp;
131 else if(! strcmp(value, "stdio"))
132 controller->backend = sio_stdio;
133 else
134 hw_abort (me, "illegal value for backend parameter `%s':"
135 "use tcp or stdio", value);
136 }
137 }
138
139
140 static void
141 m68hc11sio_finish (struct hw *me)
142 {
143 struct m68hc11sio *controller;
144
145 controller = HW_ZALLOC (me, struct m68hc11sio);
146 me->overlap_mode_hw = 1;
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 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 void
319 m68hc11sio_tx_poll (struct hw *me, void *data)
320 {
321 SIM_DESC sd;
322 struct m68hc11sio *controller;
323 sim_cpu *cpu;
324 int check_interrupt = 0;
325
326 controller = hw_data (me);
327 sd = hw_system (me);
328 cpu = STATE_CPU (sd, 0);
329
330 cpu->ios[M6811_SCSR] |= M6811_TDRE;
331 cpu->ios[M6811_SCSR] |= M6811_TC;
332
333 /* Transmitter is enabled and we have something to sent. */
334 if ((cpu->ios[M6811_SCCR2] & M6811_TE) && controller->tx_has_char)
335 {
336 cpu->ios[M6811_SCSR] &= ~M6811_TDRE;
337 cpu->ios[M6811_SCSR] &= ~M6811_TC;
338 controller->tx_has_char = 0;
339 check_interrupt = 1;
340 switch (controller->backend)
341 {
342 case sio_tcp:
343 dv_sockser_write (sd, controller->tx_char);
344 break;
345
346 case sio_stdio:
347 sim_io_write_stdout (sd, &controller->tx_char, 1);
348 sim_io_flush_stdout (sd);
349 break;
350
351 default:
352 break;
353 }
354 }
355
356 if (controller->tx_poll_event)
357 {
358 hw_event_queue_deschedule (me, controller->tx_poll_event);
359 controller->tx_poll_event = 0;
360 }
361
362 if ((cpu->ios[M6811_SCCR2] & M6811_TE)
363 && ((cpu->ios[M6811_SCSR] & M6811_TC) == 0))
364 {
365 unsigned long clock_cycle;
366
367 /* Compute CPU clock cycles to wait for the next character. */
368 clock_cycle = controller->data_length * controller->baud_cycle;
369
370 controller->tx_poll_event = hw_event_queue_schedule (me, clock_cycle,
371 m68hc11sio_tx_poll,
372 NULL);
373 }
374
375 if (check_interrupt)
376 interrupts_update_pending (&cpu->cpu_interrupts);
377 }
378
379 /* Descriptions of the SIO I/O ports. These descriptions are only used to
380 give information of the SIO device under GDB. */
381 io_reg_desc sccr2_desc[] = {
382 { M6811_TIE, "TIE ", "Transmit Interrupt Enable" },
383 { M6811_TCIE, "TCIE ", "Transmit Complete Interrupt Enable" },
384 { M6811_RIE, "RIE ", "Receive Interrupt Enable" },
385 { M6811_ILIE, "ILIE ", "Idle Line Interrupt Enable" },
386 { M6811_TE, "TE ", "Transmit Enable" },
387 { M6811_RE, "RE ", "Receive Enable" },
388 { M6811_RWU, "RWU ", "Receiver Wake Up" },
389 { M6811_SBK, "SBRK ", "Send Break" },
390 { 0, 0, 0 }
391 };
392
393 io_reg_desc sccr1_desc[] = {
394 { M6811_R8, "R8 ", "Receive Data bit 8" },
395 { M6811_T8, "T8 ", "Transmit Data bit 8" },
396 { M6811_M, "M ", "SCI Character length (0=8-bits, 1=9-bits)" },
397 { M6811_WAKE, "WAKE ", "Wake up method select (0=idle, 1=addr mark" },
398 { 0, 0, 0 }
399 };
400
401 io_reg_desc scsr_desc[] = {
402 { M6811_TDRE, "TDRE ", "Transmit Data Register Empty" },
403 { M6811_TC, "TC ", "Transmit Complete" },
404 { M6811_RDRF, "RDRF ", "Receive Data Register Full" },
405 { M6811_IDLE, "IDLE ", "Idle Line Detect" },
406 { M6811_OR, "OR ", "Overrun Error" },
407 { M6811_NF, "NF ", "Noise Flag" },
408 { M6811_FE, "FE ", "Framing Error" },
409 { 0, 0, 0 }
410 };
411
412 io_reg_desc baud_desc[] = {
413 { M6811_TCLR, "TCLR ", "Clear baud rate (test mode)" },
414 { M6811_SCP1, "SCP1 ", "SCI baud rate prescaler select (SCP1)" },
415 { M6811_SCP0, "SCP0 ", "SCI baud rate prescaler select (SCP0)" },
416 { M6811_RCKB, "RCKB ", "Baur Rate Clock Check (test mode)" },
417 { M6811_SCR2, "SCR2 ", "SCI Baud rate select (SCR2)" },
418 { M6811_SCR1, "SCR1 ", "SCI Baud rate select (SCR1)" },
419 { M6811_SCR0, "SCR0 ", "SCI Baud rate select (SCR0)" },
420 { 0, 0, 0 }
421 };
422
423 static void
424 m68hc11sio_info (struct hw *me)
425 {
426 SIM_DESC sd;
427 uint16 base = 0;
428 sim_cpu *cpu;
429 struct m68hc11sio *controller;
430 uint8 val;
431 long clock_cycle;
432
433 sd = hw_system (me);
434 cpu = STATE_CPU (sd, 0);
435 controller = hw_data (me);
436
437 sim_io_printf (sd, "M68HC11 SIO:\n");
438
439 base = cpu_get_io_base (cpu);
440
441 val = cpu->ios[M6811_BAUD];
442 print_io_byte (sd, "BAUD ", baud_desc, val, base + M6811_BAUD);
443 sim_io_printf (sd, " (%ld baud)\n",
444 (cpu->cpu_frequency / 4) / controller->baud_cycle);
445
446 val = cpu->ios[M6811_SCCR1];
447 print_io_byte (sd, "SCCR1", sccr1_desc, val, base + M6811_SCCR1);
448 sim_io_printf (sd, " (%d bits) (%dN1)\n",
449 controller->data_length, controller->data_length - 2);
450
451 val = cpu->ios[M6811_SCCR2];
452 print_io_byte (sd, "SCCR2", sccr2_desc, val, base + M6811_SCCR2);
453 sim_io_printf (sd, "\n");
454
455 val = cpu->ios[M6811_SCSR];
456 print_io_byte (sd, "SCSR ", scsr_desc, val, base + M6811_SCSR);
457 sim_io_printf (sd, "\n");
458
459 clock_cycle = controller->data_length * controller->baud_cycle;
460
461 if (controller->tx_poll_event)
462 {
463 signed64 t;
464 int n;
465
466 t = hw_event_remain_time (me, controller->tx_poll_event);
467 n = (clock_cycle - t) / controller->baud_cycle;
468 n = controller->data_length - n;
469 sim_io_printf (sd, " Transmit finished in %ld cycles (%d bit%s)\n",
470 (long) t, n, (n > 1 ? "s" : ""));
471 }
472 if (controller->rx_poll_event)
473 {
474 signed64 t;
475
476 t = hw_event_remain_time (me, controller->rx_poll_event);
477 sim_io_printf (sd, " Receive finished in %ld cycles\n",
478 (long) t);
479 }
480
481 }
482
483 static int
484 m68hc11sio_ioctl (struct hw *me,
485 hw_ioctl_request request,
486 va_list ap)
487 {
488 m68hc11sio_info (me);
489 return 0;
490 }
491
492 /* generic read/write */
493
494 static unsigned
495 m68hc11sio_io_read_buffer (struct hw *me,
496 void *dest,
497 int space,
498 unsigned_word base,
499 unsigned nr_bytes)
500 {
501 SIM_DESC sd;
502 struct m68hc11sio *controller;
503 sim_cpu *cpu;
504 unsigned8 val;
505
506 HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes));
507
508 sd = hw_system (me);
509 cpu = STATE_CPU (sd, 0);
510 controller = hw_data (me);
511
512 switch (base)
513 {
514 case M6811_SCSR:
515 controller->rx_clear_scsr = cpu->ios[M6811_SCSR]
516 & (M6811_RDRF | M6811_IDLE | M6811_OR | M6811_NF | M6811_FE);
517
518 case M6811_BAUD:
519 case M6811_SCCR1:
520 case M6811_SCCR2:
521 val = cpu->ios[base];
522 break;
523
524 case M6811_SCDR:
525 if (controller->rx_clear_scsr)
526 {
527 cpu->ios[M6811_SCSR] &= ~controller->rx_clear_scsr;
528 }
529 val = controller->rx_char;
530 break;
531
532 default:
533 return 0;
534 }
535 *((unsigned8*) dest) = val;
536 return 1;
537 }
538
539 static unsigned
540 m68hc11sio_io_write_buffer (struct hw *me,
541 const void *source,
542 int space,
543 unsigned_word base,
544 unsigned nr_bytes)
545 {
546 SIM_DESC sd;
547 struct m68hc11sio *controller;
548 sim_cpu *cpu;
549 unsigned8 val;
550
551 HW_TRACE ((me, "write 0x%08lx %d", (long) base, (int) nr_bytes));
552
553 sd = hw_system (me);
554 cpu = STATE_CPU (sd, 0);
555 controller = hw_data (me);
556
557 val = *((const unsigned8*) source);
558 switch (base)
559 {
560 case M6811_BAUD:
561 {
562 long divisor;
563 long baud;
564
565 cpu->ios[M6811_BAUD] = val;
566 switch (val & (M6811_SCP1|M6811_SCP0))
567 {
568 case M6811_BAUD_DIV_1:
569 divisor = 1 * 16;
570 break;
571
572 case M6811_BAUD_DIV_3:
573 divisor = 3 * 16;
574 break;
575
576 case M6811_BAUD_DIV_4:
577 divisor = 4 * 16;
578 break;
579
580 default:
581 case M6811_BAUD_DIV_13:
582 divisor = 13 * 16;
583 break;
584 }
585 val &= (M6811_SCR2|M6811_SCR1|M6811_SCR0);
586 divisor *= (1 << val);
587
588 baud = (cpu->cpu_frequency / 4) / divisor;
589
590 HW_TRACE ((me, "divide rate %ld, baud rate %ld",
591 divisor, baud));
592
593 controller->baud_cycle = divisor;
594 }
595 break;
596
597 case M6811_SCCR1:
598 {
599 if (val & M6811_M)
600 controller->data_length = 11;
601 else
602 controller->data_length = 10;
603
604 cpu->ios[M6811_SCCR1] = val;
605 }
606 break;
607
608 case M6811_SCCR2:
609 if ((val & M6811_RE) == 0)
610 {
611 val &= ~(M6811_RDRF|M6811_IDLE|M6811_OR|M6811_NF|M6811_NF);
612 val |= (cpu->ios[M6811_SCCR2]
613 & (M6811_RDRF|M6811_IDLE|M6811_OR|M6811_NF|M6811_NF));
614 cpu->ios[M6811_SCCR2] = val;
615 break;
616 }
617
618 /* Activate reception. */
619 if (controller->rx_poll_event == 0)
620 {
621 long clock_cycle;
622
623 /* Compute CPU clock cycles to wait for the next character. */
624 clock_cycle = controller->data_length * controller->baud_cycle;
625
626 controller->rx_poll_event = hw_event_queue_schedule (me, clock_cycle,
627 m68hc11sio_rx_poll,
628 NULL);
629 }
630 cpu->ios[M6811_SCCR2] = val;
631 interrupts_update_pending (&cpu->cpu_interrupts);
632 break;
633
634 /* No effect. */
635 case M6811_SCSR:
636 return 1;
637
638 case M6811_SCDR:
639 if (!(cpu->ios[M6811_SCSR] & M6811_TDRE))
640 {
641 return 0;
642 }
643
644 controller->tx_char = val;
645 controller->tx_has_char = 1;
646 if ((cpu->ios[M6811_SCCR2] & M6811_TE)
647 && controller->tx_poll_event == 0)
648 {
649 m68hc11sio_tx_poll (me, NULL);
650 }
651 return 1;
652
653 default:
654 return 0;
655 }
656 return nr_bytes;
657 }
658
659
660 const struct hw_descriptor dv_m68hc11sio_descriptor[] = {
661 { "m68hc11sio", m68hc11sio_finish, },
662 { NULL },
663 };
664
This page took 0.042999 seconds and 5 git commands to generate.