OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [tags/] [gdb/] [gdb-6.8/] [gdb-6.8.openrisc-2.1/] [sim/] [mn10300/] [dv-mn103ser.c] - Diff between revs 24 and 33

Only display areas with differences | Details | Blame | View Log

Rev 24 Rev 33
/*  This file is part of the program GDB, the GNU debugger.
/*  This file is part of the program GDB, the GNU debugger.
 
 
    Copyright (C) 1998, 2007, 2008 Free Software Foundation, Inc.
    Copyright (C) 1998, 2007, 2008 Free Software Foundation, Inc.
    Contributed by Cygnus Solutions.
    Contributed by Cygnus Solutions.
 
 
    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"
 
 
 
 
/* DEVICE
/* DEVICE
 
 
 
 
   mn103ser - mn103002 serial devices 0, 1 and 2.
   mn103ser - mn103002 serial devices 0, 1 and 2.
 
 
 
 
   DESCRIPTION
   DESCRIPTION
 
 
   Implements the mn103002 serial interfaces as described in the
   Implements the mn103002 serial interfaces as described in the
   mn103002 user guide.
   mn103002 user guide.
 
 
 
 
   PROPERTIES
   PROPERTIES
 
 
   reg = <serial-addr> <serial-size>
   reg = <serial-addr> <serial-size>
 
 
 
 
   BUGS
   BUGS
 
 
   */
   */
 
 
 
 
/* The serial devices' registers' address block */
/* The serial devices' registers' address block */
 
 
struct mn103ser_block {
struct mn103ser_block {
  unsigned_word base;
  unsigned_word base;
  unsigned_word bound;
  unsigned_word bound;
};
};
 
 
 
 
 
 
enum serial_register_types {
enum serial_register_types {
    SC0CTR,
    SC0CTR,
    SC1CTR,
    SC1CTR,
    SC2CTR,
    SC2CTR,
    SC0ICR,
    SC0ICR,
    SC1ICR,
    SC1ICR,
    SC2ICR,
    SC2ICR,
    SC0TXB,
    SC0TXB,
    SC1TXB,
    SC1TXB,
    SC2TXB,
    SC2TXB,
    SC0RXB,
    SC0RXB,
    SC1RXB,
    SC1RXB,
    SC2RXB,
    SC2RXB,
    SC0STR,
    SC0STR,
    SC1STR,
    SC1STR,
    SC2STR,
    SC2STR,
    SC2TIM,
    SC2TIM,
};
};
 
 
 
 
/* Access dv-sockser state */
/* Access dv-sockser state */
extern char* sockser_addr;
extern char* sockser_addr;
#define USE_SOCKSER_P (sockser_addr != NULL)
#define USE_SOCKSER_P (sockser_addr != NULL)
 
 
 
 
#define NR_SERIAL_DEVS  3
#define NR_SERIAL_DEVS  3
#define SIO_STAT_RRDY 0x0010
#define SIO_STAT_RRDY 0x0010
 
 
typedef struct _mn10300_serial {
typedef struct _mn10300_serial {
  unsigned16 status, control;
  unsigned16 status, control;
  unsigned8  txb, rxb, intmode;
  unsigned8  txb, rxb, intmode;
  struct hw_event *event;
  struct hw_event *event;
} mn10300_serial;
} mn10300_serial;
 
 
 
 
 
 
struct mn103ser {
struct mn103ser {
  struct mn103ser_block block;
  struct mn103ser_block block;
  mn10300_serial device[NR_SERIAL_DEVS];
  mn10300_serial device[NR_SERIAL_DEVS];
  unsigned8      serial2_timer_reg;
  unsigned8      serial2_timer_reg;
  do_hw_poll_read_method *reader;
  do_hw_poll_read_method *reader;
};
};
 
 
/* output port ID's */
/* output port ID's */
 
 
/* for mn103002 */
/* for mn103002 */
enum {
enum {
  SERIAL0_RECEIVE,
  SERIAL0_RECEIVE,
  SERIAL1_RECEIVE,
  SERIAL1_RECEIVE,
  SERIAL2_RECEIVE,
  SERIAL2_RECEIVE,
  SERIAL0_SEND,
  SERIAL0_SEND,
  SERIAL1_SEND,
  SERIAL1_SEND,
  SERIAL2_SEND,
  SERIAL2_SEND,
};
};
 
 
 
 
static const struct hw_port_descriptor mn103ser_ports[] = {
static const struct hw_port_descriptor mn103ser_ports[] = {
 
 
  { "serial-0-receive",  SERIAL0_RECEIVE, 0, output_port, },
  { "serial-0-receive",  SERIAL0_RECEIVE, 0, output_port, },
  { "serial-1-receive",  SERIAL1_RECEIVE, 0, output_port, },
  { "serial-1-receive",  SERIAL1_RECEIVE, 0, output_port, },
  { "serial-2-receive",  SERIAL2_RECEIVE, 0, output_port, },
  { "serial-2-receive",  SERIAL2_RECEIVE, 0, output_port, },
  { "serial-0-transmit", SERIAL0_SEND, 0, output_port, },
  { "serial-0-transmit", SERIAL0_SEND, 0, output_port, },
  { "serial-1-transmit", SERIAL1_SEND, 0, output_port, },
  { "serial-1-transmit", SERIAL1_SEND, 0, output_port, },
  { "serial-2-transmit", SERIAL2_SEND, 0, output_port, },
  { "serial-2-transmit", SERIAL2_SEND, 0, output_port, },
 
 
  { NULL, },
  { NULL, },
};
};
 
 
 
 
 
 
/* 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 mn103ser_io_read_buffer;
static hw_io_read_buffer_method mn103ser_io_read_buffer;
static hw_io_write_buffer_method mn103ser_io_write_buffer;
static hw_io_write_buffer_method mn103ser_io_write_buffer;
 
 
static void
static void
attach_mn103ser_regs (struct hw *me,
attach_mn103ser_regs (struct hw *me,
                      struct mn103ser *serial)
                      struct mn103ser *serial)
{
{
  unsigned_word attach_address;
  unsigned_word attach_address;
  int attach_space;
  int attach_space;
  unsigned attach_size;
  unsigned attach_size;
  reg_property_spec reg;
  reg_property_spec reg;
 
 
  if (hw_find_property (me, "reg") == NULL)
  if (hw_find_property (me, "reg") == NULL)
    hw_abort (me, "Missing \"reg\" property");
    hw_abort (me, "Missing \"reg\" property");
 
 
  if (!hw_find_reg_array_property (me, "reg", 0, &reg))
  if (!hw_find_reg_array_property (me, "reg", 0, &reg))
    hw_abort (me, "\"reg\" property must contain three addr/size entries");
    hw_abort (me, "\"reg\" property must contain three addr/size entries");
  hw_unit_address_to_attach_address (hw_parent (me),
  hw_unit_address_to_attach_address (hw_parent (me),
                                     &reg.address,
                                     &reg.address,
                                     &attach_space,
                                     &attach_space,
                                     &attach_address,
                                     &attach_address,
                                     me);
                                     me);
  serial->block.base = attach_address;
  serial->block.base = attach_address;
  hw_unit_size_to_attach_size (hw_parent (me),
  hw_unit_size_to_attach_size (hw_parent (me),
                               &reg.size,
                               &reg.size,
                               &attach_size, me);
                               &attach_size, me);
  serial->block.bound = attach_address + (attach_size - 1);
  serial->block.bound = attach_address + (attach_size - 1);
  hw_attach_address (hw_parent (me),
  hw_attach_address (hw_parent (me),
                     0,
                     0,
                     attach_space, attach_address, attach_size,
                     attach_space, attach_address, attach_size,
                     me);
                     me);
}
}
 
 
static void
static void
mn103ser_finish (struct hw *me)
mn103ser_finish (struct hw *me)
{
{
  struct mn103ser *serial;
  struct mn103ser *serial;
  int i;
  int i;
 
 
  serial = HW_ZALLOC (me, struct mn103ser);
  serial = HW_ZALLOC (me, struct mn103ser);
  set_hw_data (me, serial);
  set_hw_data (me, serial);
  set_hw_io_read_buffer (me, mn103ser_io_read_buffer);
  set_hw_io_read_buffer (me, mn103ser_io_read_buffer);
  set_hw_io_write_buffer (me, mn103ser_io_write_buffer);
  set_hw_io_write_buffer (me, mn103ser_io_write_buffer);
  set_hw_ports (me, mn103ser_ports);
  set_hw_ports (me, mn103ser_ports);
 
 
  /* Attach ourself to our parent bus */
  /* Attach ourself to our parent bus */
  attach_mn103ser_regs (me, serial);
  attach_mn103ser_regs (me, serial);
 
 
  /* If so configured, enable polled input */
  /* If so configured, enable polled input */
  if (hw_find_property (me, "poll?") != NULL
  if (hw_find_property (me, "poll?") != NULL
      && hw_find_boolean_property (me, "poll?"))
      && hw_find_boolean_property (me, "poll?"))
    {
    {
      serial->reader = sim_io_poll_read;
      serial->reader = sim_io_poll_read;
    }
    }
  else
  else
    {
    {
      serial->reader = sim_io_read;
      serial->reader = sim_io_read;
    }
    }
 
 
  /* Initialize the serial device registers. */
  /* Initialize the serial device registers. */
  for ( i=0; i<NR_SERIAL_DEVS; ++i )
  for ( i=0; i<NR_SERIAL_DEVS; ++i )
    {
    {
      serial->device[i].txb = 0;
      serial->device[i].txb = 0;
      serial->device[i].rxb = 0;
      serial->device[i].rxb = 0;
      serial->device[i].status = 0;
      serial->device[i].status = 0;
      serial->device[i].control = 0;
      serial->device[i].control = 0;
      serial->device[i].intmode = 0;
      serial->device[i].intmode = 0;
      serial->device[i].event = NULL;
      serial->device[i].event = NULL;
    }
    }
}
}
 
 
 
 
/* read and write */
/* read and write */
 
 
static int
static int
decode_addr (struct hw *me,
decode_addr (struct hw *me,
             struct mn103ser *serial,
             struct mn103ser *serial,
             unsigned_word address)
             unsigned_word address)
{
{
  unsigned_word offset;
  unsigned_word offset;
  offset = address - serial->block.base;
  offset = address - serial->block.base;
  switch (offset)
  switch (offset)
    {
    {
    case 0x00: return SC0CTR;
    case 0x00: return SC0CTR;
    case 0x04: return SC0ICR;
    case 0x04: return SC0ICR;
    case 0x08: return SC0TXB;
    case 0x08: return SC0TXB;
    case 0x09: return SC0RXB;
    case 0x09: return SC0RXB;
    case 0x0C: return SC0STR;
    case 0x0C: return SC0STR;
    case 0x10: return SC1CTR;
    case 0x10: return SC1CTR;
    case 0x14: return SC1ICR;
    case 0x14: return SC1ICR;
    case 0x18: return SC1TXB;
    case 0x18: return SC1TXB;
    case 0x19: return SC1RXB;
    case 0x19: return SC1RXB;
    case 0x1C: return SC1STR;
    case 0x1C: return SC1STR;
    case 0x20: return SC2CTR;
    case 0x20: return SC2CTR;
    case 0x24: return SC2ICR;
    case 0x24: return SC2ICR;
    case 0x28: return SC2TXB;
    case 0x28: return SC2TXB;
    case 0x29: return SC2RXB;
    case 0x29: return SC2RXB;
    case 0x2C: return SC2STR;
    case 0x2C: return SC2STR;
    case 0x2D: return SC2TIM;
    case 0x2D: return SC2TIM;
    default:
    default:
      {
      {
        hw_abort (me, "bad address");
        hw_abort (me, "bad address");
        return -1;
        return -1;
      }
      }
    }
    }
}
}
 
 
static void
static void
do_polling_event (struct hw *me,
do_polling_event (struct hw *me,
                  void *data)
                  void *data)
{
{
  struct mn103ser *serial = hw_data(me);
  struct mn103ser *serial = hw_data(me);
  long serial_reg = (long) data;
  long serial_reg = (long) data;
  char c;
  char c;
  int count;
  int count;
 
 
  if(USE_SOCKSER_P)
  if(USE_SOCKSER_P)
    {
    {
      int rd;
      int rd;
      rd = dv_sockser_read (hw_system (me));
      rd = dv_sockser_read (hw_system (me));
      if(rd != -1)
      if(rd != -1)
        {
        {
          c = (char) rd;
          c = (char) rd;
          count = 1;
          count = 1;
        }
        }
      else
      else
        {
        {
          count = HW_IO_NOT_READY;
          count = HW_IO_NOT_READY;
        }
        }
    }
    }
  else
  else
    {
    {
      count = do_hw_poll_read (me, serial->reader,
      count = do_hw_poll_read (me, serial->reader,
                               0/*STDIN*/, &c, sizeof(c));
                               0/*STDIN*/, &c, sizeof(c));
    }
    }
 
 
 
 
  switch (count)
  switch (count)
    {
    {
    case HW_IO_NOT_READY:
    case HW_IO_NOT_READY:
    case HW_IO_EOF:
    case HW_IO_EOF:
      serial->device[serial_reg].rxb = 0;
      serial->device[serial_reg].rxb = 0;
      serial->device[serial_reg].status &= ~SIO_STAT_RRDY;
      serial->device[serial_reg].status &= ~SIO_STAT_RRDY;
      break;
      break;
    default:
    default:
      serial->device[serial_reg].rxb = c;
      serial->device[serial_reg].rxb = c;
      serial->device[serial_reg].status |= SIO_STAT_RRDY;
      serial->device[serial_reg].status |= SIO_STAT_RRDY;
      hw_port_event (me, serial_reg+SERIAL0_RECEIVE, 1);
      hw_port_event (me, serial_reg+SERIAL0_RECEIVE, 1);
    }
    }
 
 
  /* Schedule next polling event */
  /* Schedule next polling event */
  serial->device[serial_reg].event
  serial->device[serial_reg].event
    = hw_event_queue_schedule (me, 1000,
    = hw_event_queue_schedule (me, 1000,
                               do_polling_event, (void *)serial_reg);
                               do_polling_event, (void *)serial_reg);
 
 
}
}
 
 
static void
static void
read_control_reg (struct hw *me,
read_control_reg (struct hw *me,
                  struct mn103ser *serial,
                  struct mn103ser *serial,
                  unsigned_word serial_reg,
                  unsigned_word serial_reg,
                  void *dest,
                  void *dest,
                  unsigned  nr_bytes)
                  unsigned  nr_bytes)
{
{
  /* really allow 1 byte read, too */
  /* really allow 1 byte read, too */
  if ( nr_bytes == 2 )
  if ( nr_bytes == 2 )
    {
    {
      *(unsigned16 *)dest = H2LE_2 (serial->device[serial_reg].control);
      *(unsigned16 *)dest = H2LE_2 (serial->device[serial_reg].control);
    }
    }
  else
  else
    {
    {
      hw_abort (me, "bad read size of %d bytes from SC%dCTR.", nr_bytes,
      hw_abort (me, "bad read size of %d bytes from SC%dCTR.", nr_bytes,
                serial_reg);
                serial_reg);
    }
    }
}
}
 
 
 
 
static void
static void
read_intmode_reg (struct hw *me,
read_intmode_reg (struct hw *me,
                  struct mn103ser *serial,
                  struct mn103ser *serial,
                  unsigned_word serial_reg,
                  unsigned_word serial_reg,
                  void *dest,
                  void *dest,
                  unsigned  nr_bytes)
                  unsigned  nr_bytes)
{
{
  if ( nr_bytes == 1 )
  if ( nr_bytes == 1 )
    {
    {
      *(unsigned8 *)dest = serial->device[serial_reg].intmode;
      *(unsigned8 *)dest = serial->device[serial_reg].intmode;
    }
    }
  else
  else
    {
    {
      hw_abort (me, "bad read size of %d bytes from SC%dICR.", nr_bytes,
      hw_abort (me, "bad read size of %d bytes from SC%dICR.", nr_bytes,
                serial_reg);
                serial_reg);
    }
    }
}
}
 
 
 
 
static void
static void
read_txb (struct hw *me,
read_txb (struct hw *me,
          struct mn103ser *serial,
          struct mn103ser *serial,
          unsigned_word serial_reg,
          unsigned_word serial_reg,
          void *dest,
          void *dest,
          unsigned  nr_bytes)
          unsigned  nr_bytes)
{
{
  if ( nr_bytes == 1 )
  if ( nr_bytes == 1 )
    {
    {
      *(unsigned8 *)dest = serial->device[serial_reg].txb;
      *(unsigned8 *)dest = serial->device[serial_reg].txb;
    }
    }
  else
  else
    {
    {
      hw_abort (me, "bad read size of %d bytes from SC%dTXB.", nr_bytes,
      hw_abort (me, "bad read size of %d bytes from SC%dTXB.", nr_bytes,
                serial_reg);
                serial_reg);
    }
    }
}
}
 
 
 
 
static void
static void
read_rxb (struct hw *me,
read_rxb (struct hw *me,
          struct mn103ser *serial,
          struct mn103ser *serial,
          unsigned_word serial_reg,
          unsigned_word serial_reg,
          void *dest,
          void *dest,
          unsigned  nr_bytes)
          unsigned  nr_bytes)
{
{
  if ( nr_bytes == 1 )
  if ( nr_bytes == 1 )
    {
    {
      *(unsigned8 *)dest = serial->device[serial_reg].rxb;
      *(unsigned8 *)dest = serial->device[serial_reg].rxb;
      /* Reception buffer is now empty. */
      /* Reception buffer is now empty. */
      serial->device[serial_reg].status &= ~SIO_STAT_RRDY;
      serial->device[serial_reg].status &= ~SIO_STAT_RRDY;
    }
    }
  else
  else
    {
    {
      hw_abort (me, "bad read size of %d bytes from SC%dRXB.", nr_bytes,
      hw_abort (me, "bad read size of %d bytes from SC%dRXB.", nr_bytes,
                serial_reg);
                serial_reg);
    }
    }
}
}
 
 
 
 
static void
static void
read_status_reg (struct hw *me,
read_status_reg (struct hw *me,
                 struct mn103ser *serial,
                 struct mn103ser *serial,
                 unsigned_word serial_reg,
                 unsigned_word serial_reg,
                 void *dest,
                 void *dest,
                 unsigned  nr_bytes)
                 unsigned  nr_bytes)
{
{
  char c;
  char c;
  int count;
  int count;
 
 
  if ( (serial->device[serial_reg].status & SIO_STAT_RRDY) == 0 )
  if ( (serial->device[serial_reg].status & SIO_STAT_RRDY) == 0 )
    {
    {
      /* FIFO is empty */
      /* FIFO is empty */
      /* Kill current poll event */
      /* Kill current poll event */
      if ( NULL != serial->device[serial_reg].event )
      if ( NULL != serial->device[serial_reg].event )
        {
        {
          hw_event_queue_deschedule (me, serial->device[serial_reg].event);
          hw_event_queue_deschedule (me, serial->device[serial_reg].event);
          serial->device[serial_reg].event = NULL;
          serial->device[serial_reg].event = NULL;
        }
        }
 
 
      if(USE_SOCKSER_P)
      if(USE_SOCKSER_P)
        {
        {
          int rd;
          int rd;
          rd = dv_sockser_read (hw_system (me));
          rd = dv_sockser_read (hw_system (me));
          if(rd != -1)
          if(rd != -1)
            {
            {
              c = (char) rd;
              c = (char) rd;
              count = 1;
              count = 1;
            }
            }
          else
          else
            {
            {
              count = HW_IO_NOT_READY;
              count = HW_IO_NOT_READY;
            }
            }
        }
        }
      else
      else
        {
        {
          count = do_hw_poll_read (me, serial->reader,
          count = do_hw_poll_read (me, serial->reader,
                                   0/*STDIN*/, &c, sizeof(c));
                                   0/*STDIN*/, &c, sizeof(c));
        }
        }
 
 
      switch (count)
      switch (count)
        {
        {
        case HW_IO_NOT_READY:
        case HW_IO_NOT_READY:
        case HW_IO_EOF:
        case HW_IO_EOF:
          serial->device[serial_reg].rxb = 0;
          serial->device[serial_reg].rxb = 0;
          serial->device[serial_reg].status &= ~SIO_STAT_RRDY;
          serial->device[serial_reg].status &= ~SIO_STAT_RRDY;
          break;
          break;
        default:
        default:
          serial->device[serial_reg].rxb = c;
          serial->device[serial_reg].rxb = c;
          serial->device[serial_reg].status |= SIO_STAT_RRDY;
          serial->device[serial_reg].status |= SIO_STAT_RRDY;
          hw_port_event (me, serial_reg+SERIAL0_RECEIVE, 1);
          hw_port_event (me, serial_reg+SERIAL0_RECEIVE, 1);
        }
        }
 
 
      /* schedule polling event */
      /* schedule polling event */
      serial->device[serial_reg].event
      serial->device[serial_reg].event
        = hw_event_queue_schedule (me, 1000,
        = hw_event_queue_schedule (me, 1000,
                                   do_polling_event,
                                   do_polling_event,
                                   (void *) (long) serial_reg);
                                   (void *) (long) serial_reg);
    }
    }
 
 
  if ( nr_bytes == 1 )
  if ( nr_bytes == 1 )
    {
    {
      *(unsigned8 *)dest = (unsigned8)serial->device[serial_reg].status;
      *(unsigned8 *)dest = (unsigned8)serial->device[serial_reg].status;
    }
    }
  else if ( nr_bytes == 2 && serial_reg != SC2STR )
  else if ( nr_bytes == 2 && serial_reg != SC2STR )
    {
    {
      *(unsigned16 *)dest = H2LE_2 (serial->device[serial_reg].status);
      *(unsigned16 *)dest = H2LE_2 (serial->device[serial_reg].status);
    }
    }
  else
  else
    {
    {
      hw_abort (me, "bad read size of %d bytes from SC%dSTR.", nr_bytes,
      hw_abort (me, "bad read size of %d bytes from SC%dSTR.", nr_bytes,
                serial_reg);
                serial_reg);
    }
    }
}
}
 
 
 
 
static void
static void
read_serial2_timer_reg (struct hw *me,
read_serial2_timer_reg (struct hw *me,
                        struct mn103ser *serial,
                        struct mn103ser *serial,
                        void *dest,
                        void *dest,
                        unsigned  nr_bytes)
                        unsigned  nr_bytes)
{
{
  if ( nr_bytes == 1 )
  if ( nr_bytes == 1 )
    {
    {
      * (unsigned8 *) dest = (unsigned8) serial->serial2_timer_reg;
      * (unsigned8 *) dest = (unsigned8) serial->serial2_timer_reg;
    }
    }
  else
  else
    {
    {
      hw_abort (me, "bad read size of %d bytes to SC2TIM.", nr_bytes);
      hw_abort (me, "bad read size of %d bytes to SC2TIM.", nr_bytes);
    }
    }
}
}
 
 
 
 
static unsigned
static unsigned
mn103ser_io_read_buffer (struct hw *me,
mn103ser_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)
{
{
  struct mn103ser *serial = hw_data (me);
  struct mn103ser *serial = hw_data (me);
  enum serial_register_types serial_reg;
  enum serial_register_types serial_reg;
  HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes));
  HW_TRACE ((me, "read 0x%08lx %d", (long) base, (int) nr_bytes));
 
 
  serial_reg = decode_addr (me, serial, base);
  serial_reg = decode_addr (me, serial, base);
  switch (serial_reg)
  switch (serial_reg)
    {
    {
    /* control registers */
    /* control registers */
    case SC0CTR:
    case SC0CTR:
    case SC1CTR:
    case SC1CTR:
    case SC2CTR:
    case SC2CTR:
      read_control_reg(me, serial, serial_reg-SC0CTR, dest, nr_bytes);
      read_control_reg(me, serial, serial_reg-SC0CTR, dest, nr_bytes);
      HW_TRACE ((me, "read - ctrl reg%d has 0x%x\n", serial_reg-SC0CTR,
      HW_TRACE ((me, "read - ctrl reg%d has 0x%x\n", serial_reg-SC0CTR,
                 *(unsigned8 *)dest));
                 *(unsigned8 *)dest));
      break;
      break;
 
 
    /* interrupt mode registers */
    /* interrupt mode registers */
    case SC0ICR:
    case SC0ICR:
    case SC1ICR:
    case SC1ICR:
    case SC2ICR:
    case SC2ICR:
      read_intmode_reg(me, serial, serial_reg-SC0ICR, dest, nr_bytes);
      read_intmode_reg(me, serial, serial_reg-SC0ICR, dest, nr_bytes);
      HW_TRACE ((me, "read - intmode reg%d has 0x%x\n", serial_reg-SC0ICR,
      HW_TRACE ((me, "read - intmode reg%d has 0x%x\n", serial_reg-SC0ICR,
                 *(unsigned8 *)dest));
                 *(unsigned8 *)dest));
      break;
      break;
 
 
    /* transmission buffers */
    /* transmission buffers */
    case SC0TXB:
    case SC0TXB:
    case SC1TXB:
    case SC1TXB:
    case SC2TXB:
    case SC2TXB:
      read_txb(me, serial, serial_reg-SC0TXB, dest, nr_bytes);
      read_txb(me, serial, serial_reg-SC0TXB, dest, nr_bytes);
      HW_TRACE ((me, "read - txb%d has %c\n", serial_reg-SC0TXB,
      HW_TRACE ((me, "read - txb%d has %c\n", serial_reg-SC0TXB,
                 *(char *)dest));
                 *(char *)dest));
      break;
      break;
 
 
    /* reception buffers */
    /* reception buffers */
    case SC0RXB:
    case SC0RXB:
    case SC1RXB:
    case SC1RXB:
    case SC2RXB:
    case SC2RXB:
      read_rxb(me, serial, serial_reg-SC0RXB, dest, nr_bytes);
      read_rxb(me, serial, serial_reg-SC0RXB, dest, nr_bytes);
      HW_TRACE ((me, "read - rxb%d has %c\n", serial_reg-SC0RXB,
      HW_TRACE ((me, "read - rxb%d has %c\n", serial_reg-SC0RXB,
                 *(char *)dest));
                 *(char *)dest));
     break;
     break;
 
 
    /* status registers */
    /* status registers */
    case SC0STR:
    case SC0STR:
    case SC1STR:
    case SC1STR:
    case SC2STR:
    case SC2STR:
      read_status_reg(me, serial, serial_reg-SC0STR, dest, nr_bytes);
      read_status_reg(me, serial, serial_reg-SC0STR, dest, nr_bytes);
      HW_TRACE ((me, "read - status reg%d has 0x%x\n", serial_reg-SC0STR,
      HW_TRACE ((me, "read - status reg%d has 0x%x\n", serial_reg-SC0STR,
                 *(unsigned8 *)dest));
                 *(unsigned8 *)dest));
      break;
      break;
 
 
    case SC2TIM:
    case SC2TIM:
      read_serial2_timer_reg(me, serial, dest, nr_bytes);
      read_serial2_timer_reg(me, serial, dest, nr_bytes);
      HW_TRACE ((me, "read - serial2 timer reg %d\n", *(unsigned8 *)dest));
      HW_TRACE ((me, "read - serial2 timer reg %d\n", *(unsigned8 *)dest));
      break;
      break;
 
 
    default:
    default:
      hw_abort(me, "invalid address");
      hw_abort(me, "invalid address");
    }
    }
 
 
  return nr_bytes;
  return nr_bytes;
}
}
 
 
 
 
static void
static void
write_control_reg (struct hw *me,
write_control_reg (struct hw *me,
                   struct mn103ser *serial,
                   struct mn103ser *serial,
                   unsigned_word serial_reg,
                   unsigned_word serial_reg,
                   const void *source,
                   const void *source,
                   unsigned  nr_bytes)
                   unsigned  nr_bytes)
{
{
  unsigned16 val = LE2H_2 (*(unsigned16 *)source);
  unsigned16 val = LE2H_2 (*(unsigned16 *)source);
 
 
  /* really allow 1 byte write, too */
  /* really allow 1 byte write, too */
  if ( nr_bytes == 2 )
  if ( nr_bytes == 2 )
    {
    {
      if ( serial_reg == 2 && (val & 0x0C04) != 0 )
      if ( serial_reg == 2 && (val & 0x0C04) != 0 )
        {
        {
          hw_abort(me, "Cannot write to read-only bits of SC2CTR.");
          hw_abort(me, "Cannot write to read-only bits of SC2CTR.");
        }
        }
      else
      else
        {
        {
          serial->device[serial_reg].control = val;
          serial->device[serial_reg].control = val;
        }
        }
    }
    }
  else
  else
    {
    {
      hw_abort (me, "bad read size of %d bytes from SC%dSTR.", nr_bytes,
      hw_abort (me, "bad read size of %d bytes from SC%dSTR.", nr_bytes,
                serial_reg);
                serial_reg);
    }
    }
}
}
 
 
 
 
static void
static void
write_intmode_reg (struct hw *me,
write_intmode_reg (struct hw *me,
                   struct mn103ser *serial,
                   struct mn103ser *serial,
                   unsigned_word serial_reg,
                   unsigned_word serial_reg,
                   const void *source,
                   const void *source,
                   unsigned  nr_bytes)
                   unsigned  nr_bytes)
{
{
unsigned8 val = *(unsigned8 *)source;
unsigned8 val = *(unsigned8 *)source;
 
 
  if ( nr_bytes == 1 )
  if ( nr_bytes == 1 )
    {
    {
      /* Check for attempt to write to read-only bits of register. */
      /* Check for attempt to write to read-only bits of register. */
      if ( ( serial_reg == 2 && (val & 0xCA) != 0 )
      if ( ( serial_reg == 2 && (val & 0xCA) != 0 )
           || ( serial_reg != 2 && (val & 0x4A) != 0 ) )
           || ( serial_reg != 2 && (val & 0x4A) != 0 ) )
        {
        {
          hw_abort(me, "Cannot write to read-only bits of SC%dICR.",
          hw_abort(me, "Cannot write to read-only bits of SC%dICR.",
                   serial_reg);
                   serial_reg);
        }
        }
      else
      else
        {
        {
          serial->device[serial_reg].intmode = val;
          serial->device[serial_reg].intmode = val;
        }
        }
    }
    }
  else
  else
    {
    {
      hw_abort (me, "bad write size of %d bytes to SC%dICR.", nr_bytes,
      hw_abort (me, "bad write size of %d bytes to SC%dICR.", nr_bytes,
                serial_reg);
                serial_reg);
    }
    }
}
}
 
 
 
 
static void
static void
write_txb (struct hw *me,
write_txb (struct hw *me,
           struct mn103ser *serial,
           struct mn103ser *serial,
           unsigned_word serial_reg,
           unsigned_word serial_reg,
           const void *source,
           const void *source,
           unsigned  nr_bytes)
           unsigned  nr_bytes)
{
{
  if ( nr_bytes == 1 )
  if ( nr_bytes == 1 )
    {
    {
      serial->device[serial_reg].txb = *(unsigned8 *)source;
      serial->device[serial_reg].txb = *(unsigned8 *)source;
 
 
      if(USE_SOCKSER_P)
      if(USE_SOCKSER_P)
        {
        {
          dv_sockser_write(hw_system (me), * (char*) source);
          dv_sockser_write(hw_system (me), * (char*) source);
        }
        }
      else
      else
        {
        {
          sim_io_write_stdout(hw_system (me), (char *)source, 1);
          sim_io_write_stdout(hw_system (me), (char *)source, 1);
          sim_io_flush_stdout(hw_system (me));
          sim_io_flush_stdout(hw_system (me));
        }
        }
 
 
      hw_port_event (me, serial_reg+SERIAL0_SEND, 1);
      hw_port_event (me, serial_reg+SERIAL0_SEND, 1);
    }
    }
  else
  else
    {
    {
      hw_abort (me, "bad write size of %d bytes to SC%dTXB.", nr_bytes,
      hw_abort (me, "bad write size of %d bytes to SC%dTXB.", nr_bytes,
                serial_reg);
                serial_reg);
    }
    }
}
}
 
 
 
 
static void
static void
write_serial2_timer_reg (struct hw *me,
write_serial2_timer_reg (struct hw *me,
                         struct mn103ser *serial,
                         struct mn103ser *serial,
                         const void *source,
                         const void *source,
                         unsigned  nr_bytes)
                         unsigned  nr_bytes)
{
{
  if ( nr_bytes == 1 )
  if ( nr_bytes == 1 )
    {
    {
      serial->serial2_timer_reg = *(unsigned8 *)source;
      serial->serial2_timer_reg = *(unsigned8 *)source;
    }
    }
  else
  else
    {
    {
      hw_abort (me, "bad write size of %d bytes to SC2TIM.", nr_bytes);
      hw_abort (me, "bad write size of %d bytes to SC2TIM.", nr_bytes);
    }
    }
}
}
 
 
 
 
static unsigned
static unsigned
mn103ser_io_write_buffer (struct hw *me,
mn103ser_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)
{
{
  struct mn103ser *serial = hw_data (me);
  struct mn103ser *serial = hw_data (me);
  enum serial_register_types serial_reg;
  enum serial_register_types serial_reg;
  HW_TRACE ((me, "write 0x%08lx %d", (long) base, (int) nr_bytes));
  HW_TRACE ((me, "write 0x%08lx %d", (long) base, (int) nr_bytes));
 
 
  serial_reg = decode_addr (me, serial, base);
  serial_reg = decode_addr (me, serial, base);
  switch (serial_reg)
  switch (serial_reg)
    {
    {
    /* control registers */
    /* control registers */
    case SC0CTR:
    case SC0CTR:
    case SC1CTR:
    case SC1CTR:
    case SC2CTR:
    case SC2CTR:
      HW_TRACE ((me, "write - ctrl reg%d has 0x%x, nrbytes=%d.\n",
      HW_TRACE ((me, "write - ctrl reg%d has 0x%x, nrbytes=%d.\n",
                 serial_reg-SC0CTR, *(unsigned8 *)source, nr_bytes));
                 serial_reg-SC0CTR, *(unsigned8 *)source, nr_bytes));
      write_control_reg(me, serial, serial_reg-SC0CTR, source, nr_bytes);
      write_control_reg(me, serial, serial_reg-SC0CTR, source, nr_bytes);
      break;
      break;
 
 
    /* interrupt mode registers */
    /* interrupt mode registers */
    case SC0ICR:
    case SC0ICR:
    case SC1ICR:
    case SC1ICR:
    case SC2ICR:
    case SC2ICR:
      HW_TRACE ((me, "write - intmode reg%d has 0x%x, nrbytes=%d.\n",
      HW_TRACE ((me, "write - intmode reg%d has 0x%x, nrbytes=%d.\n",
                 serial_reg-SC0ICR, *(unsigned8 *)source, nr_bytes));
                 serial_reg-SC0ICR, *(unsigned8 *)source, nr_bytes));
      write_intmode_reg(me, serial, serial_reg-SC0ICR, source, nr_bytes);
      write_intmode_reg(me, serial, serial_reg-SC0ICR, source, nr_bytes);
      break;
      break;
 
 
    /* transmission buffers */
    /* transmission buffers */
    case SC0TXB:
    case SC0TXB:
    case SC1TXB:
    case SC1TXB:
    case SC2TXB:
    case SC2TXB:
      HW_TRACE ((me, "write - txb%d has %c, nrbytes=%d.\n",
      HW_TRACE ((me, "write - txb%d has %c, nrbytes=%d.\n",
                 serial_reg-SC0TXB, *(char *)source, nr_bytes));
                 serial_reg-SC0TXB, *(char *)source, nr_bytes));
      write_txb(me, serial, serial_reg-SC0TXB, source, nr_bytes);
      write_txb(me, serial, serial_reg-SC0TXB, source, nr_bytes);
      break;
      break;
 
 
    /* reception buffers */
    /* reception buffers */
    case SC0RXB:
    case SC0RXB:
    case SC1RXB:
    case SC1RXB:
    case SC2RXB:
    case SC2RXB:
      hw_abort(me, "Cannot write to reception buffer.");
      hw_abort(me, "Cannot write to reception buffer.");
     break;
     break;
 
 
    /* status registers */
    /* status registers */
    case SC0STR:
    case SC0STR:
    case SC1STR:
    case SC1STR:
    case SC2STR:
    case SC2STR:
      hw_abort(me, "Cannot write to status register.");
      hw_abort(me, "Cannot write to status register.");
      break;
      break;
 
 
    case SC2TIM:
    case SC2TIM:
      HW_TRACE ((me, "read - serial2 timer reg %d (nrbytes=%d)\n",
      HW_TRACE ((me, "read - serial2 timer reg %d (nrbytes=%d)\n",
                 *(unsigned8 *)source, nr_bytes));
                 *(unsigned8 *)source, nr_bytes));
      write_serial2_timer_reg(me, serial, source, nr_bytes);
      write_serial2_timer_reg(me, serial, source, nr_bytes);
      break;
      break;
 
 
    default:
    default:
      hw_abort(me, "invalid address");
      hw_abort(me, "invalid address");
    }
    }
 
 
  return nr_bytes;
  return nr_bytes;
}
}
 
 
 
 
const struct hw_descriptor dv_mn103ser_descriptor[] = {
const struct hw_descriptor dv_mn103ser_descriptor[] = {
  { "mn103ser", mn103ser_finish, },
  { "mn103ser", mn103ser_finish, },
  { NULL },
  { NULL },
};
};
 
 

powered by: WebSVN 2.1.0

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