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