Home | History | Annotate | Line # | Download | only in m68hc11
      1       1.1  christos /*  dv-m68hc11sio.c -- Simulation of the 68HC11 serial device.
      2  1.1.1.10  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.1.1.9  christos /* This must come before any other includes.  */
     24   1.1.1.9  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.1.1.10  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.1.1.10  christos   struct m68hc11_sim_cpu *m68hc11_cpu;
    189   1.1.1.9  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.1.1.10  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.1.1.10  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.1.1.10  christos         if (((m68hc11_cpu->ios[M6811_HPRIO]) & (M6811_SMOD | M6811_MDA)) == M6811_SMOD)
    229       1.1  christos           {
    230  1.1.1.10  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.1.1.6  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.1.1.10  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.1.1.10  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.1.1.10  christos       if (m68hc11_cpu->ios[M6811_SCSR] & M6811_RDRF)
    287  1.1.1.10  christos         m68hc11_cpu->ios[M6811_SCSR] |= M6811_OR;
    288       1.1  christos 
    289  1.1.1.10  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.1.1.10  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.1.1.10  christos       interrupts_update_pending (&m68hc11_cpu->cpu_interrupts);
    320       1.1  christos }
    321       1.1  christos 
    322       1.1  christos 
    323   1.1.1.6  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.1.1.10  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.1.1.10  christos   m68hc11_cpu  = M68HC11_SIM_CPU (cpu);
    335       1.1  christos 
    336  1.1.1.10  christos   m68hc11_cpu->ios[M6811_SCSR] |= M6811_TDRE;
    337  1.1.1.10  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.1.1.10  christos   if ((m68hc11_cpu->ios[M6811_SCCR2] & M6811_TE) && controller->tx_has_char)
    341       1.1  christos     {
    342  1.1.1.10  christos       m68hc11_cpu->ios[M6811_SCSR] &= ~M6811_TDRE;
    343  1.1.1.10  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.1.1.9  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.1.1.10  christos   if ((m68hc11_cpu->ios[M6811_SCCR2] & M6811_TE)
    368  1.1.1.10  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.1.1.10  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.1.1.9  christos   uint16_t base = 0;
    432       1.1  christos   sim_cpu *cpu;
    433  1.1.1.10  christos   struct m68hc11_sim_cpu *m68hc11_cpu;
    434       1.1  christos   struct m68hc11sio *controller;
    435   1.1.1.9  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.1.1.10  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.1.1.10  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.1.1.10  christos                  (m68hc11_cpu->cpu_frequency / 4) / controller->baud_cycle);
    451       1.1  christos 
    452  1.1.1.10  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.1.1.10  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.1.1.10  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.1.1.9  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.1.1.9  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.1.1.10  christos   struct m68hc11_sim_cpu *m68hc11_cpu;
    512   1.1.1.9  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.1.1.10  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.1.1.10  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.1.1.10  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.1.1.10  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.1.1.10  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.1.1.9  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.1.1.10  christos   struct m68hc11_sim_cpu *m68hc11_cpu;
    560   1.1.1.9  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.1.1.10  christos   m68hc11_cpu = M68HC11_SIM_CPU (cpu);
    567       1.1  christos   controller = hw_data (me);
    568       1.1  christos 
    569   1.1.1.9  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.1.1.10  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.1.1.10  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.1.1.10  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.1.1.10  christos           val |= (m68hc11_cpu->ios[M6811_SCCR2]
    625       1.1  christos                   & (M6811_RDRF|M6811_IDLE|M6811_OR|M6811_NF|M6811_NF));
    626  1.1.1.10  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.1.1.10  christos       m68hc11_cpu->ios[M6811_SCCR2] = val;
    643  1.1.1.10  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.1.1.10  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.1.1.10  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