OpenCores
URL https://opencores.org/ocsvn/openrisc_2011-10-31/openrisc_2011-10-31/trunk

Subversion Repositories openrisc_2011-10-31

[/] [openrisc/] [tags/] [gnu-src/] [gdb-6.8/] [pre-binutils-2.20.1-sync/] [sim/] [m68hc11/] [dv-m68hc11sio.c] - Diff between revs 24 and 157

Go to most recent revision | Only display areas with differences | Details | Blame | View Log

Rev 24 Rev 157
/*  dv-m68hc11sio.c -- Simulation of the 68HC11 serial device.
/*  dv-m68hc11sio.c -- Simulation of the 68HC11 serial device.
    Copyright (C) 1999, 2000, 2001, 2007, 2008 Free Software Foundation, Inc.
    Copyright (C) 1999, 2000, 2001, 2007, 2008 Free Software Foundation, Inc.
    Written by Stephane Carrez (stcarrez@worldnet.fr)
    Written by Stephane Carrez (stcarrez@worldnet.fr)
    (From a driver model Contributed by Cygnus Solutions.)
    (From a driver model Contributed by Cygnus Solutions.)
 
 
    This file is part of the program GDB, the GNU debugger.
    This file is part of the program GDB, the GNU debugger.
 
 
    This program is free software; you can redistribute it and/or modify
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    (at your option) any later version.
 
 
    This program is distributed in the hope that it will be useful,
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
    GNU General Public License for more details.
 
 
    You should have received a copy of the GNU General Public License
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 
    */
    */
 
 
 
 
#include "sim-main.h"
#include "sim-main.h"
#include "hw-main.h"
#include "hw-main.h"
#include "dv-sockser.h"
#include "dv-sockser.h"
#include "sim-assert.h"
#include "sim-assert.h"
 
 
 
 
/* DEVICE
/* DEVICE
 
 
        m68hc11sio - m68hc11 serial I/O
        m68hc11sio - m68hc11 serial I/O
 
 
 
 
   DESCRIPTION
   DESCRIPTION
 
 
        Implements the m68hc11 serial I/O controller described in the m68hc11
        Implements the m68hc11 serial I/O controller described in the m68hc11
        user guide. The serial I/O controller is directly connected to the CPU
        user guide. The serial I/O controller is directly connected to the CPU
        interrupt. The simulator implements:
        interrupt. The simulator implements:
 
 
            - baud rate emulation
            - baud rate emulation
            - 8-bits transfers
            - 8-bits transfers
 
 
   PROPERTIES
   PROPERTIES
 
 
   backend {tcp | stdio}
   backend {tcp | stdio}
 
 
        Use dv-sockser TCP-port backend or stdio for backend.  Default: stdio.
        Use dv-sockser TCP-port backend or stdio for backend.  Default: stdio.
 
 
 
 
   PORTS
   PORTS
 
 
   reset (input)
   reset (input)
 
 
        Reset port. This port is only used to simulate a reset of the serial
        Reset port. This port is only used to simulate a reset of the serial
        I/O controller. It should be connected to the RESET output of the cpu.
        I/O controller. It should be connected to the RESET output of the cpu.
 
 
   */
   */
 
 
 
 
 
 
/* port ID's */
/* port ID's */
 
 
enum
enum
{
{
  RESET_PORT
  RESET_PORT
};
};
 
 
 
 
static const struct hw_port_descriptor m68hc11sio_ports[] =
static const struct hw_port_descriptor m68hc11sio_ports[] =
{
{
  { "reset", RESET_PORT, 0, input_port, },
  { "reset", RESET_PORT, 0, input_port, },
  { NULL, },
  { NULL, },
};
};
 
 
 
 
/* Serial Controller information.  */
/* Serial Controller information.  */
struct m68hc11sio
struct m68hc11sio
{
{
  enum {sio_tcp, sio_stdio} backend; /* backend */
  enum {sio_tcp, sio_stdio} backend; /* backend */
 
 
  /* Number of cpu cycles to send a bit on the wire.  */
  /* Number of cpu cycles to send a bit on the wire.  */
  unsigned long baud_cycle;
  unsigned long baud_cycle;
 
 
  /* Length in bits of characters sent, this includes the
  /* Length in bits of characters sent, this includes the
     start/stop and parity bits.  Together with baud_cycle, this
     start/stop and parity bits.  Together with baud_cycle, this
     is used to find the number of cpu cycles to send/receive a data.  */
     is used to find the number of cpu cycles to send/receive a data.  */
  unsigned int  data_length;
  unsigned int  data_length;
 
 
  /* Information about next character to be transmited.  */
  /* Information about next character to be transmited.  */
  unsigned char tx_has_char;
  unsigned char tx_has_char;
  unsigned char tx_char;
  unsigned char tx_char;
 
 
  unsigned char rx_char;
  unsigned char rx_char;
  unsigned char rx_clear_scsr;
  unsigned char rx_clear_scsr;
 
 
  /* Periodic I/O polling.  */
  /* Periodic I/O polling.  */
  struct hw_event* tx_poll_event;
  struct hw_event* tx_poll_event;
  struct hw_event* rx_poll_event;
  struct hw_event* rx_poll_event;
};
};
 
 
 
 
 
 
/* Finish off the partially created hw device.  Attach our local
/* Finish off the partially created hw device.  Attach our local
   callbacks.  Wire up our port names etc.  */
   callbacks.  Wire up our port names etc.  */
 
 
static hw_io_read_buffer_method m68hc11sio_io_read_buffer;
static hw_io_read_buffer_method m68hc11sio_io_read_buffer;
static hw_io_write_buffer_method m68hc11sio_io_write_buffer;
static hw_io_write_buffer_method m68hc11sio_io_write_buffer;
static hw_port_event_method m68hc11sio_port_event;
static hw_port_event_method m68hc11sio_port_event;
static hw_ioctl_method m68hc11sio_ioctl;
static hw_ioctl_method m68hc11sio_ioctl;
 
 
#define M6811_SCI_FIRST_REG (M6811_BAUD)
#define M6811_SCI_FIRST_REG (M6811_BAUD)
#define M6811_SCI_LAST_REG  (M6811_SCDR)
#define M6811_SCI_LAST_REG  (M6811_SCDR)
 
 
 
 
static void
static void
attach_m68hc11sio_regs (struct hw *me,
attach_m68hc11sio_regs (struct hw *me,
                        struct m68hc11sio *controller)
                        struct m68hc11sio *controller)
{
{
  hw_attach_address (hw_parent (me), M6811_IO_LEVEL, io_map,
  hw_attach_address (hw_parent (me), M6811_IO_LEVEL, io_map,
                     M6811_SCI_FIRST_REG,
                     M6811_SCI_FIRST_REG,
                     M6811_SCI_LAST_REG - M6811_SCI_FIRST_REG + 1,
                     M6811_SCI_LAST_REG - M6811_SCI_FIRST_REG + 1,
                     me);
                     me);
 
 
  if (hw_find_property(me, "backend") != NULL)
  if (hw_find_property(me, "backend") != NULL)
    {
    {
      const char *value = hw_find_string_property(me, "backend");
      const char *value = hw_find_string_property(me, "backend");
      if(! strcmp(value, "tcp"))
      if(! strcmp(value, "tcp"))
        controller->backend = sio_tcp;
        controller->backend = sio_tcp;
      else if(! strcmp(value, "stdio"))
      else if(! strcmp(value, "stdio"))
        controller->backend = sio_stdio;
        controller->backend = sio_stdio;
      else
      else
        hw_abort (me, "illegal value for backend parameter `%s':"
        hw_abort (me, "illegal value for backend parameter `%s':"
                  "use tcp or stdio", value);
                  "use tcp or stdio", value);
    }
    }
}
}
 
 
 
 
static void
static void
m68hc11sio_finish (struct hw *me)
m68hc11sio_finish (struct hw *me)
{
{
  struct m68hc11sio *controller;
  struct m68hc11sio *controller;
 
 
  controller = HW_ZALLOC (me, struct m68hc11sio);
  controller = HW_ZALLOC (me, struct m68hc11sio);
  set_hw_data (me, controller);
  set_hw_data (me, controller);
  set_hw_io_read_buffer (me, m68hc11sio_io_read_buffer);
  set_hw_io_read_buffer (me, m68hc11sio_io_read_buffer);
  set_hw_io_write_buffer (me, m68hc11sio_io_write_buffer);
  set_hw_io_write_buffer (me, m68hc11sio_io_write_buffer);
  set_hw_ports (me, m68hc11sio_ports);
  set_hw_ports (me, m68hc11sio_ports);
  set_hw_port_event (me, m68hc11sio_port_event);
  set_hw_port_event (me, m68hc11sio_port_event);
#ifdef set_hw_ioctl
#ifdef set_hw_ioctl
  set_hw_ioctl (me, m68hc11sio_ioctl);
  set_hw_ioctl (me, m68hc11sio_ioctl);
#else
#else
  me->to_ioctl = m68hc11sio_ioctl;
  me->to_ioctl = m68hc11sio_ioctl;
#endif
#endif
 
 
  /* Preset defaults.  */
  /* Preset defaults.  */
  controller->backend = sio_stdio;
  controller->backend = sio_stdio;
 
 
  /* Attach ourself to our parent bus.  */
  /* Attach ourself to our parent bus.  */
  attach_m68hc11sio_regs (me, controller);
  attach_m68hc11sio_regs (me, controller);
 
 
  /* Initialize to reset state.  */
  /* Initialize to reset state.  */
  controller->tx_poll_event = NULL;
  controller->tx_poll_event = NULL;
  controller->rx_poll_event = NULL;
  controller->rx_poll_event = NULL;
  controller->tx_char       = 0;
  controller->tx_char       = 0;
  controller->tx_has_char   = 0;
  controller->tx_has_char   = 0;
  controller->rx_clear_scsr = 0;
  controller->rx_clear_scsr = 0;
  controller->rx_char       = 0;
  controller->rx_char       = 0;
}
}
 
 
 
 
 
 
/* An event arrives on an interrupt port.  */
/* An event arrives on an interrupt port.  */
 
 
static void
static void
m68hc11sio_port_event (struct hw *me,
m68hc11sio_port_event (struct hw *me,
                       int my_port,
                       int my_port,
                       struct hw *source,
                       struct hw *source,
                       int source_port,
                       int source_port,
                       int level)
                       int level)
{
{
  SIM_DESC sd;
  SIM_DESC sd;
  struct m68hc11sio *controller;
  struct m68hc11sio *controller;
  sim_cpu *cpu;
  sim_cpu *cpu;
  unsigned8 val;
  unsigned8 val;
 
 
  controller = hw_data (me);
  controller = hw_data (me);
  sd         = hw_system (me);
  sd         = hw_system (me);
  cpu        = STATE_CPU (sd, 0);
  cpu        = STATE_CPU (sd, 0);
  switch (my_port)
  switch (my_port)
    {
    {
    case RESET_PORT:
    case RESET_PORT:
      {
      {
        HW_TRACE ((me, "SCI reset"));
        HW_TRACE ((me, "SCI reset"));
 
 
        /* Reset the state of SCI registers.  */
        /* Reset the state of SCI registers.  */
        val = 0;
        val = 0;
        m68hc11sio_io_write_buffer (me, &val, io_map,
        m68hc11sio_io_write_buffer (me, &val, io_map,
                                    (unsigned_word) M6811_BAUD, 1);
                                    (unsigned_word) M6811_BAUD, 1);
        m68hc11sio_io_write_buffer (me, &val, io_map,
        m68hc11sio_io_write_buffer (me, &val, io_map,
                                    (unsigned_word) M6811_SCCR1, 1);
                                    (unsigned_word) M6811_SCCR1, 1);
        m68hc11sio_io_write_buffer (me, &val, io_map,
        m68hc11sio_io_write_buffer (me, &val, io_map,
                                    (unsigned_word) M6811_SCCR2, 1);
                                    (unsigned_word) M6811_SCCR2, 1);
 
 
        cpu->ios[M6811_SCSR]    = M6811_TC | M6811_TDRE;
        cpu->ios[M6811_SCSR]    = M6811_TC | M6811_TDRE;
        controller->rx_char     = 0;
        controller->rx_char     = 0;
        controller->tx_char     = 0;
        controller->tx_char     = 0;
        controller->tx_has_char = 0;
        controller->tx_has_char = 0;
        controller->rx_clear_scsr = 0;
        controller->rx_clear_scsr = 0;
        if (controller->rx_poll_event)
        if (controller->rx_poll_event)
          {
          {
            hw_event_queue_deschedule (me, controller->rx_poll_event);
            hw_event_queue_deschedule (me, controller->rx_poll_event);
            controller->rx_poll_event = 0;
            controller->rx_poll_event = 0;
          }
          }
        if (controller->tx_poll_event)
        if (controller->tx_poll_event)
          {
          {
            hw_event_queue_deschedule (me, controller->tx_poll_event);
            hw_event_queue_deschedule (me, controller->tx_poll_event);
            controller->tx_poll_event = 0;
            controller->tx_poll_event = 0;
          }
          }
 
 
        /* In bootstrap mode, initialize the SCI to 1200 bauds to
        /* In bootstrap mode, initialize the SCI to 1200 bauds to
           simulate some initial setup by the internal rom.  */
           simulate some initial setup by the internal rom.  */
        if (((cpu->ios[M6811_HPRIO]) & (M6811_SMOD | M6811_MDA)) == M6811_SMOD)
        if (((cpu->ios[M6811_HPRIO]) & (M6811_SMOD | M6811_MDA)) == M6811_SMOD)
          {
          {
            unsigned char val = 0x33;
            unsigned char val = 0x33;
 
 
            m68hc11sio_io_write_buffer (me, &val, io_map,
            m68hc11sio_io_write_buffer (me, &val, io_map,
                                        (unsigned_word) M6811_BAUD, 1);
                                        (unsigned_word) M6811_BAUD, 1);
            val = 0x12;
            val = 0x12;
            m68hc11sio_io_write_buffer (me, &val, io_map,
            m68hc11sio_io_write_buffer (me, &val, io_map,
                                        (unsigned_word) M6811_SCCR2, 1);
                                        (unsigned_word) M6811_SCCR2, 1);
          }
          }
        break;
        break;
      }
      }
 
 
    default:
    default:
      hw_abort (me, "Event on unknown port %d", my_port);
      hw_abort (me, "Event on unknown port %d", my_port);
      break;
      break;
    }
    }
}
}
 
 
 
 
void
void
m68hc11sio_rx_poll (struct hw *me, void *data)
m68hc11sio_rx_poll (struct hw *me, void *data)
{
{
  SIM_DESC sd;
  SIM_DESC sd;
  struct m68hc11sio *controller;
  struct m68hc11sio *controller;
  sim_cpu *cpu;
  sim_cpu *cpu;
  char cc;
  char cc;
  int cnt;
  int cnt;
  int check_interrupt = 0;
  int check_interrupt = 0;
 
 
  controller = hw_data (me);
  controller = hw_data (me);
  sd         = hw_system (me);
  sd         = hw_system (me);
  cpu        = STATE_CPU (sd, 0);
  cpu        = STATE_CPU (sd, 0);
  switch (controller->backend)
  switch (controller->backend)
    {
    {
    case sio_tcp:
    case sio_tcp:
      cnt = dv_sockser_read (sd);
      cnt = dv_sockser_read (sd);
      if (cnt != -1)
      if (cnt != -1)
        {
        {
          cc = (char) cnt;
          cc = (char) cnt;
          cnt = 1;
          cnt = 1;
        }
        }
      break;
      break;
 
 
    case sio_stdio:
    case sio_stdio:
      cnt = sim_io_poll_read (sd, 0 /* stdin */, &cc, 1);
      cnt = sim_io_poll_read (sd, 0 /* stdin */, &cc, 1);
      break;
      break;
 
 
    default:
    default:
      cnt = 0;
      cnt = 0;
      break;
      break;
    }
    }
 
 
  if (cnt == 1)
  if (cnt == 1)
    {
    {
      /* Raise the overrun flag if the previous character was not read.  */
      /* Raise the overrun flag if the previous character was not read.  */
      if (cpu->ios[M6811_SCSR] & M6811_RDRF)
      if (cpu->ios[M6811_SCSR] & M6811_RDRF)
        cpu->ios[M6811_SCSR] |= M6811_OR;
        cpu->ios[M6811_SCSR] |= M6811_OR;
 
 
      cpu->ios[M6811_SCSR]     |= M6811_RDRF;
      cpu->ios[M6811_SCSR]     |= M6811_RDRF;
      controller->rx_char       = cc;
      controller->rx_char       = cc;
      controller->rx_clear_scsr = 0;
      controller->rx_clear_scsr = 0;
      check_interrupt = 1;
      check_interrupt = 1;
    }
    }
  else
  else
    {
    {
      /* handle idle line detect here.  */
      /* handle idle line detect here.  */
      ;
      ;
    }
    }
 
 
  if (controller->rx_poll_event)
  if (controller->rx_poll_event)
    {
    {
      hw_event_queue_deschedule (me, controller->rx_poll_event);
      hw_event_queue_deschedule (me, controller->rx_poll_event);
      controller->rx_poll_event = 0;
      controller->rx_poll_event = 0;
    }
    }
 
 
  if (cpu->ios[M6811_SCCR2] & M6811_RE)
  if (cpu->ios[M6811_SCCR2] & M6811_RE)
    {
    {
      unsigned long clock_cycle;
      unsigned long clock_cycle;
 
 
      /* Compute CPU clock cycles to wait for the next character.  */
      /* Compute CPU clock cycles to wait for the next character.  */
      clock_cycle = controller->data_length * controller->baud_cycle;
      clock_cycle = controller->data_length * controller->baud_cycle;
 
 
      controller->rx_poll_event = hw_event_queue_schedule (me, clock_cycle,
      controller->rx_poll_event = hw_event_queue_schedule (me, clock_cycle,
                                                           m68hc11sio_rx_poll,
                                                           m68hc11sio_rx_poll,
                                                           NULL);
                                                           NULL);
    }
    }
 
 
  if (check_interrupt)
  if (check_interrupt)
      interrupts_update_pending (&cpu->cpu_interrupts);
      interrupts_update_pending (&cpu->cpu_interrupts);
}
}
 
 
 
 
void
void
m68hc11sio_tx_poll (struct hw *me, void *data)
m68hc11sio_tx_poll (struct hw *me, void *data)
{
{
  SIM_DESC sd;
  SIM_DESC sd;
  struct m68hc11sio *controller;
  struct m68hc11sio *controller;
  sim_cpu *cpu;
  sim_cpu *cpu;
 
 
  controller = hw_data (me);
  controller = hw_data (me);
  sd         = hw_system (me);
  sd         = hw_system (me);
  cpu        = STATE_CPU (sd, 0);
  cpu        = STATE_CPU (sd, 0);
 
 
  cpu->ios[M6811_SCSR] |= M6811_TDRE;
  cpu->ios[M6811_SCSR] |= M6811_TDRE;
  cpu->ios[M6811_SCSR] |= M6811_TC;
  cpu->ios[M6811_SCSR] |= M6811_TC;
 
 
  /* Transmitter is enabled and we have something to send.  */
  /* Transmitter is enabled and we have something to send.  */
  if ((cpu->ios[M6811_SCCR2] & M6811_TE) && controller->tx_has_char)
  if ((cpu->ios[M6811_SCCR2] & M6811_TE) && controller->tx_has_char)
    {
    {
      cpu->ios[M6811_SCSR] &= ~M6811_TDRE;
      cpu->ios[M6811_SCSR] &= ~M6811_TDRE;
      cpu->ios[M6811_SCSR] &= ~M6811_TC;
      cpu->ios[M6811_SCSR] &= ~M6811_TC;
      controller->tx_has_char = 0;
      controller->tx_has_char = 0;
      switch (controller->backend)
      switch (controller->backend)
        {
        {
        case sio_tcp:
        case sio_tcp:
          dv_sockser_write (sd, controller->tx_char);
          dv_sockser_write (sd, controller->tx_char);
          break;
          break;
 
 
        case sio_stdio:
        case sio_stdio:
          sim_io_write_stdout (sd, &controller->tx_char, 1);
          sim_io_write_stdout (sd, &controller->tx_char, 1);
          sim_io_flush_stdout (sd);
          sim_io_flush_stdout (sd);
          break;
          break;
 
 
        default:
        default:
          break;
          break;
        }
        }
    }
    }
 
 
  if (controller->tx_poll_event)
  if (controller->tx_poll_event)
    {
    {
      hw_event_queue_deschedule (me, controller->tx_poll_event);
      hw_event_queue_deschedule (me, controller->tx_poll_event);
      controller->tx_poll_event = 0;
      controller->tx_poll_event = 0;
    }
    }
 
 
  if ((cpu->ios[M6811_SCCR2] & M6811_TE)
  if ((cpu->ios[M6811_SCCR2] & M6811_TE)
      && ((cpu->ios[M6811_SCSR] & M6811_TC) == 0))
      && ((cpu->ios[M6811_SCSR] & M6811_TC) == 0))
    {
    {
      unsigned long clock_cycle;
      unsigned long clock_cycle;
 
 
      /* Compute CPU clock cycles to wait for the next character.  */
      /* Compute CPU clock cycles to wait for the next character.  */
      clock_cycle = controller->data_length * controller->baud_cycle;
      clock_cycle = controller->data_length * controller->baud_cycle;
 
 
      controller->tx_poll_event = hw_event_queue_schedule (me, clock_cycle,
      controller->tx_poll_event = hw_event_queue_schedule (me, clock_cycle,
                                                           m68hc11sio_tx_poll,
                                                           m68hc11sio_tx_poll,
                                                           NULL);
                                                           NULL);
    }
    }
 
 
  interrupts_update_pending (&cpu->cpu_interrupts);
  interrupts_update_pending (&cpu->cpu_interrupts);
}
}
 
 
/* Descriptions of the SIO I/O ports.  These descriptions are only used to
/* Descriptions of the SIO I/O ports.  These descriptions are only used to
   give information of the SIO device under GDB.  */
   give information of the SIO device under GDB.  */
io_reg_desc sccr2_desc[] = {
io_reg_desc sccr2_desc[] = {
  { M6811_TIE,   "TIE  ", "Transmit Interrupt Enable" },
  { M6811_TIE,   "TIE  ", "Transmit Interrupt Enable" },
  { M6811_TCIE,  "TCIE ", "Transmit Complete Interrupt Enable" },
  { M6811_TCIE,  "TCIE ", "Transmit Complete Interrupt Enable" },
  { M6811_RIE,   "RIE  ", "Receive Interrupt Enable" },
  { M6811_RIE,   "RIE  ", "Receive Interrupt Enable" },
  { M6811_ILIE,  "ILIE ", "Idle Line Interrupt Enable" },
  { M6811_ILIE,  "ILIE ", "Idle Line Interrupt Enable" },
  { M6811_TE,    "TE   ", "Transmit Enable" },
  { M6811_TE,    "TE   ", "Transmit Enable" },
  { M6811_RE,    "RE   ", "Receive Enable" },
  { M6811_RE,    "RE   ", "Receive Enable" },
  { M6811_RWU,   "RWU  ", "Receiver Wake Up" },
  { M6811_RWU,   "RWU  ", "Receiver Wake Up" },
  { M6811_SBK,   "SBRK ", "Send Break" },
  { M6811_SBK,   "SBRK ", "Send Break" },
  { 0,  0, 0 }
  { 0,  0, 0 }
};
};
 
 
io_reg_desc sccr1_desc[] = {
io_reg_desc sccr1_desc[] = {
  { M6811_R8,    "R8   ", "Receive Data bit 8" },
  { M6811_R8,    "R8   ", "Receive Data bit 8" },
  { M6811_T8,    "T8   ", "Transmit Data bit 8" },
  { M6811_T8,    "T8   ", "Transmit Data bit 8" },
  { M6811_M,     "M    ", "SCI Character length (0=8-bits, 1=9-bits)" },
  { M6811_M,     "M    ", "SCI Character length (0=8-bits, 1=9-bits)" },
  { M6811_WAKE,  "WAKE ", "Wake up method select (0=idle, 1=addr mark" },
  { M6811_WAKE,  "WAKE ", "Wake up method select (0=idle, 1=addr mark" },
  { 0,  0, 0 }
  { 0,  0, 0 }
};
};
 
 
io_reg_desc scsr_desc[] = {
io_reg_desc scsr_desc[] = {
  { M6811_TDRE,  "TDRE ", "Transmit Data Register Empty" },
  { M6811_TDRE,  "TDRE ", "Transmit Data Register Empty" },
  { M6811_TC,    "TC   ", "Transmit Complete" },
  { M6811_TC,    "TC   ", "Transmit Complete" },
  { M6811_RDRF,  "RDRF ", "Receive Data Register Full" },
  { M6811_RDRF,  "RDRF ", "Receive Data Register Full" },
  { M6811_IDLE,  "IDLE ", "Idle Line Detect" },
  { M6811_IDLE,  "IDLE ", "Idle Line Detect" },
  { M6811_OR,    "OR   ", "Overrun Error" },
  { M6811_OR,    "OR   ", "Overrun Error" },
  { M6811_NF,    "NF   ", "Noise Flag" },
  { M6811_NF,    "NF   ", "Noise Flag" },
  { M6811_FE,    "FE   ", "Framing Error" },
  { M6811_FE,    "FE   ", "Framing Error" },
  { 0,  0, 0 }
  { 0,  0, 0 }
};
};
 
 
io_reg_desc baud_desc[] = {
io_reg_desc baud_desc[] = {
  { M6811_TCLR,  "TCLR ", "Clear baud rate (test mode)" },
  { M6811_TCLR,  "TCLR ", "Clear baud rate (test mode)" },
  { M6811_SCP1,  "SCP1 ", "SCI baud rate prescaler select (SCP1)" },
  { M6811_SCP1,  "SCP1 ", "SCI baud rate prescaler select (SCP1)" },
  { M6811_SCP0,  "SCP0 ", "SCI baud rate prescaler select (SCP0)" },
  { M6811_SCP0,  "SCP0 ", "SCI baud rate prescaler select (SCP0)" },
  { M6811_RCKB,  "RCKB ", "Baur Rate Clock Check (test mode)" },
  { M6811_RCKB,  "RCKB ", "Baur Rate Clock Check (test mode)" },
  { M6811_SCR2,  "SCR2 ", "SCI Baud rate select (SCR2)" },
  { M6811_SCR2,  "SCR2 ", "SCI Baud rate select (SCR2)" },
  { M6811_SCR1,  "SCR1 ", "SCI Baud rate select (SCR1)" },
  { M6811_SCR1,  "SCR1 ", "SCI Baud rate select (SCR1)" },
  { M6811_SCR0,  "SCR0 ", "SCI Baud rate select (SCR0)" },
  { M6811_SCR0,  "SCR0 ", "SCI Baud rate select (SCR0)" },
  { 0,  0, 0 }
  { 0,  0, 0 }
};
};
 
 
static void
static void
m68hc11sio_info (struct hw *me)
m68hc11sio_info (struct hw *me)
{
{
  SIM_DESC sd;
  SIM_DESC sd;
  uint16 base = 0;
  uint16 base = 0;
  sim_cpu *cpu;
  sim_cpu *cpu;
  struct m68hc11sio *controller;
  struct m68hc11sio *controller;
  uint8 val;
  uint8 val;
  long clock_cycle;
  long clock_cycle;
 
 
  sd = hw_system (me);
  sd = hw_system (me);
  cpu = STATE_CPU (sd, 0);
  cpu = STATE_CPU (sd, 0);
  controller = hw_data (me);
  controller = hw_data (me);
 
 
  sim_io_printf (sd, "M68HC11 SIO:\n");
  sim_io_printf (sd, "M68HC11 SIO:\n");
 
 
  base = cpu_get_io_base (cpu);
  base = cpu_get_io_base (cpu);
 
 
  val  = cpu->ios[M6811_BAUD];
  val  = cpu->ios[M6811_BAUD];
  print_io_byte (sd, "BAUD ", baud_desc, val, base + M6811_BAUD);
  print_io_byte (sd, "BAUD ", baud_desc, val, base + M6811_BAUD);
  sim_io_printf (sd, " (%ld baud)\n",
  sim_io_printf (sd, " (%ld baud)\n",
                 (cpu->cpu_frequency / 4) / controller->baud_cycle);
                 (cpu->cpu_frequency / 4) / controller->baud_cycle);
 
 
  val = cpu->ios[M6811_SCCR1];
  val = cpu->ios[M6811_SCCR1];
  print_io_byte (sd, "SCCR1", sccr1_desc, val, base + M6811_SCCR1);
  print_io_byte (sd, "SCCR1", sccr1_desc, val, base + M6811_SCCR1);
  sim_io_printf (sd, "  (%d bits) (%dN1)\n",
  sim_io_printf (sd, "  (%d bits) (%dN1)\n",
                 controller->data_length, controller->data_length - 2);
                 controller->data_length, controller->data_length - 2);
 
 
  val = cpu->ios[M6811_SCCR2];
  val = cpu->ios[M6811_SCCR2];
  print_io_byte (sd, "SCCR2", sccr2_desc, val, base + M6811_SCCR2);
  print_io_byte (sd, "SCCR2", sccr2_desc, val, base + M6811_SCCR2);
  sim_io_printf (sd, "\n");
  sim_io_printf (sd, "\n");
 
 
  val = cpu->ios[M6811_SCSR];
  val = cpu->ios[M6811_SCSR];
  print_io_byte (sd, "SCSR ", scsr_desc, val, base + M6811_SCSR);
  print_io_byte (sd, "SCSR ", scsr_desc, val, base + M6811_SCSR);
  sim_io_printf (sd, "\n");
  sim_io_printf (sd, "\n");
 
 
  clock_cycle = controller->data_length * controller->baud_cycle;
  clock_cycle = controller->data_length * controller->baud_cycle;
 
 
  if (controller->tx_poll_event)
  if (controller->tx_poll_event)
    {
    {
      signed64 t;
      signed64 t;
      int n;
      int n;
 
 
      t = hw_event_remain_time (me, controller->tx_poll_event);
      t = hw_event_remain_time (me, controller->tx_poll_event);
      n = (clock_cycle - t) / controller->baud_cycle;
      n = (clock_cycle - t) / controller->baud_cycle;
      n = controller->data_length - n;
      n = controller->data_length - n;
      sim_io_printf (sd, "  Transmit finished in %s (%d bit%s)\n",
      sim_io_printf (sd, "  Transmit finished in %s (%d bit%s)\n",
                     cycle_to_string (cpu, t, PRINT_TIME | PRINT_CYCLE),
                     cycle_to_string (cpu, t, PRINT_TIME | PRINT_CYCLE),
                     n, (n > 1 ? "s" : ""));
                     n, (n > 1 ? "s" : ""));
    }
    }
  if (controller->rx_poll_event)
  if (controller->rx_poll_event)
    {
    {
      signed64 t;
      signed64 t;
 
 
      t = hw_event_remain_time (me, controller->rx_poll_event);
      t = hw_event_remain_time (me, controller->rx_poll_event);
      sim_io_printf (sd, "  Receive finished in %s\n",
      sim_io_printf (sd, "  Receive finished in %s\n",
                     cycle_to_string (cpu, t, PRINT_TIME | PRINT_CYCLE));
                     cycle_to_string (cpu, t, PRINT_TIME | PRINT_CYCLE));
    }
    }
 
 
}
}
 
 
static int
static int
m68hc11sio_ioctl (struct hw *me,
m68hc11sio_ioctl (struct hw *me,
                  hw_ioctl_request request,
                  hw_ioctl_request request,
                  va_list ap)
                  va_list ap)
{
{
  m68hc11sio_info (me);
  m68hc11sio_info (me);
  return 0;
  return 0;
}
}
 
 
/* generic read/write */
/* generic read/write */
 
 
static unsigned
static unsigned
m68hc11sio_io_read_buffer (struct hw *me,
m68hc11sio_io_read_buffer (struct hw *me,
                           void *dest,
                           void *dest,
                           int space,
                           int space,
                           unsigned_word base,
                           unsigned_word base,
                           unsigned nr_bytes)
                           unsigned nr_bytes)
{
{
  SIM_DESC sd;
  SIM_DESC sd;
  struct m68hc11sio *controller;
  struct m68hc11sio *controller;
  sim_cpu *cpu;
  sim_cpu *cpu;
  unsigned8 val;
  unsigned8 val;
 
 
  HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes));
  HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes));
 
 
  sd  = hw_system (me);
  sd  = hw_system (me);
  cpu = STATE_CPU (sd, 0);
  cpu = STATE_CPU (sd, 0);
  controller = hw_data (me);
  controller = hw_data (me);
 
 
  switch (base)
  switch (base)
    {
    {
    case M6811_SCSR:
    case M6811_SCSR:
      controller->rx_clear_scsr = cpu->ios[M6811_SCSR]
      controller->rx_clear_scsr = cpu->ios[M6811_SCSR]
        & (M6811_RDRF | M6811_IDLE | M6811_OR | M6811_NF | M6811_FE);
        & (M6811_RDRF | M6811_IDLE | M6811_OR | M6811_NF | M6811_FE);
 
 
    case M6811_BAUD:
    case M6811_BAUD:
    case M6811_SCCR1:
    case M6811_SCCR1:
    case M6811_SCCR2:
    case M6811_SCCR2:
      val = cpu->ios[base];
      val = cpu->ios[base];
      break;
      break;
 
 
    case M6811_SCDR:
    case M6811_SCDR:
      if (controller->rx_clear_scsr)
      if (controller->rx_clear_scsr)
        {
        {
          cpu->ios[M6811_SCSR] &= ~controller->rx_clear_scsr;
          cpu->ios[M6811_SCSR] &= ~controller->rx_clear_scsr;
        }
        }
      val = controller->rx_char;
      val = controller->rx_char;
      break;
      break;
 
 
    default:
    default:
      return 0;
      return 0;
    }
    }
  *((unsigned8*) dest) = val;
  *((unsigned8*) dest) = val;
  return 1;
  return 1;
}
}
 
 
static unsigned
static unsigned
m68hc11sio_io_write_buffer (struct hw *me,
m68hc11sio_io_write_buffer (struct hw *me,
                            const void *source,
                            const void *source,
                            int space,
                            int space,
                            unsigned_word base,
                            unsigned_word base,
                            unsigned nr_bytes)
                            unsigned nr_bytes)
{
{
  SIM_DESC sd;
  SIM_DESC sd;
  struct m68hc11sio *controller;
  struct m68hc11sio *controller;
  sim_cpu *cpu;
  sim_cpu *cpu;
  unsigned8 val;
  unsigned8 val;
 
 
  HW_TRACE ((me, "write 0x%08lx %d", (long) base, (int) nr_bytes));
  HW_TRACE ((me, "write 0x%08lx %d", (long) base, (int) nr_bytes));
 
 
  sd  = hw_system (me);
  sd  = hw_system (me);
  cpu = STATE_CPU (sd, 0);
  cpu = STATE_CPU (sd, 0);
  controller = hw_data (me);
  controller = hw_data (me);
 
 
  val = *((const unsigned8*) source);
  val = *((const unsigned8*) source);
  switch (base)
  switch (base)
    {
    {
    case M6811_BAUD:
    case M6811_BAUD:
      {
      {
        long divisor;
        long divisor;
        long baud;
        long baud;
 
 
        cpu->ios[M6811_BAUD] = val;
        cpu->ios[M6811_BAUD] = val;
        switch (val & (M6811_SCP1|M6811_SCP0))
        switch (val & (M6811_SCP1|M6811_SCP0))
          {
          {
          case M6811_BAUD_DIV_1:
          case M6811_BAUD_DIV_1:
            divisor = 1 * 16;
            divisor = 1 * 16;
            break;
            break;
 
 
          case M6811_BAUD_DIV_3:
          case M6811_BAUD_DIV_3:
            divisor = 3 * 16;
            divisor = 3 * 16;
            break;
            break;
 
 
          case M6811_BAUD_DIV_4:
          case M6811_BAUD_DIV_4:
            divisor = 4 * 16;
            divisor = 4 * 16;
            break;
            break;
 
 
          default:
          default:
          case M6811_BAUD_DIV_13:
          case M6811_BAUD_DIV_13:
            divisor = 13 * 16;
            divisor = 13 * 16;
            break;
            break;
          }
          }
        val &= (M6811_SCR2|M6811_SCR1|M6811_SCR0);
        val &= (M6811_SCR2|M6811_SCR1|M6811_SCR0);
        divisor *= (1 << val);
        divisor *= (1 << val);
 
 
        baud = (cpu->cpu_frequency / 4) / divisor;
        baud = (cpu->cpu_frequency / 4) / divisor;
 
 
        HW_TRACE ((me, "divide rate %ld, baud rate %ld",
        HW_TRACE ((me, "divide rate %ld, baud rate %ld",
                   divisor, baud));
                   divisor, baud));
 
 
        controller->baud_cycle = divisor;
        controller->baud_cycle = divisor;
      }
      }
      break;
      break;
 
 
    case M6811_SCCR1:
    case M6811_SCCR1:
      {
      {
        if (val & M6811_M)
        if (val & M6811_M)
          controller->data_length = 11;
          controller->data_length = 11;
        else
        else
          controller->data_length = 10;
          controller->data_length = 10;
 
 
        cpu->ios[M6811_SCCR1] = val;
        cpu->ios[M6811_SCCR1] = val;
      }
      }
      break;
      break;
 
 
    case M6811_SCCR2:
    case M6811_SCCR2:
      if ((val & M6811_RE) == 0)
      if ((val & M6811_RE) == 0)
        {
        {
          val &= ~(M6811_RDRF|M6811_IDLE|M6811_OR|M6811_NF|M6811_NF);
          val &= ~(M6811_RDRF|M6811_IDLE|M6811_OR|M6811_NF|M6811_NF);
          val |= (cpu->ios[M6811_SCCR2]
          val |= (cpu->ios[M6811_SCCR2]
                  & (M6811_RDRF|M6811_IDLE|M6811_OR|M6811_NF|M6811_NF));
                  & (M6811_RDRF|M6811_IDLE|M6811_OR|M6811_NF|M6811_NF));
          cpu->ios[M6811_SCCR2] = val;
          cpu->ios[M6811_SCCR2] = val;
          break;
          break;
        }
        }
 
 
      /* Activate reception.  */
      /* Activate reception.  */
      if (controller->rx_poll_event == 0)
      if (controller->rx_poll_event == 0)
        {
        {
          long clock_cycle;
          long clock_cycle;
 
 
          /* Compute CPU clock cycles to wait for the next character.  */
          /* Compute CPU clock cycles to wait for the next character.  */
          clock_cycle = controller->data_length * controller->baud_cycle;
          clock_cycle = controller->data_length * controller->baud_cycle;
 
 
          controller->rx_poll_event = hw_event_queue_schedule (me, clock_cycle,
          controller->rx_poll_event = hw_event_queue_schedule (me, clock_cycle,
                                                               m68hc11sio_rx_poll,
                                                               m68hc11sio_rx_poll,
                                                               NULL);
                                                               NULL);
        }
        }
      cpu->ios[M6811_SCCR2] = val;
      cpu->ios[M6811_SCCR2] = val;
      interrupts_update_pending (&cpu->cpu_interrupts);
      interrupts_update_pending (&cpu->cpu_interrupts);
      break;
      break;
 
 
      /* No effect.  */
      /* No effect.  */
    case M6811_SCSR:
    case M6811_SCSR:
      return 1;
      return 1;
 
 
    case M6811_SCDR:
    case M6811_SCDR:
      if (!(cpu->ios[M6811_SCSR] & M6811_TDRE))
      if (!(cpu->ios[M6811_SCSR] & M6811_TDRE))
        {
        {
          return 0;
          return 0;
        }
        }
 
 
      controller->tx_char     = val;
      controller->tx_char     = val;
      controller->tx_has_char = 1;
      controller->tx_has_char = 1;
      if ((cpu->ios[M6811_SCCR2] & M6811_TE)
      if ((cpu->ios[M6811_SCCR2] & M6811_TE)
          && controller->tx_poll_event == 0)
          && controller->tx_poll_event == 0)
        {
        {
          m68hc11sio_tx_poll (me, NULL);
          m68hc11sio_tx_poll (me, NULL);
        }
        }
      return 1;
      return 1;
 
 
    default:
    default:
      return 0;
      return 0;
    }
    }
  return nr_bytes;
  return nr_bytes;
}
}
 
 
 
 
const struct hw_descriptor dv_m68hc11sio_descriptor[] = {
const struct hw_descriptor dv_m68hc11sio_descriptor[] = {
  { "m68hc11sio", m68hc11sio_finish },
  { "m68hc11sio", m68hc11sio_finish },
  { "m68hc12sio", m68hc11sio_finish },
  { "m68hc12sio", m68hc11sio_finish },
  { NULL },
  { NULL },
};
};
 
 
 
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.