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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-7.1/] [sim/] [lm32/] [dv-lm32uart.c] - Diff between revs 227 and 816

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

Rev 227 Rev 816
/*  Lattice Mico32 UART model.
/*  Lattice Mico32 UART model.
    Contributed by Jon Beniston <jon@beniston.com>
    Contributed by Jon Beniston <jon@beniston.com>
 
 
   Copyright (C) 2009, 2010 Free Software Foundation, Inc.
   Copyright (C) 2009, 2010 Free Software Foundation, Inc.
 
 
   This file is part of GDB.
   This file is part of GDB.
 
 
   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 "sim-assert.h"
#include "sim-assert.h"
 
 
#include <stdio.h>
#include <stdio.h>
#include <sys/time.h>
#include <sys/time.h>
 
 
struct lm32uart
struct lm32uart
{
{
  unsigned base;                /* Base address of this UART.  */
  unsigned base;                /* Base address of this UART.  */
  unsigned limit;               /* Limit address of this UART.  */
  unsigned limit;               /* Limit address of this UART.  */
  unsigned char rbr;
  unsigned char rbr;
  unsigned char thr;
  unsigned char thr;
  unsigned char ier;
  unsigned char ier;
  unsigned char iir;
  unsigned char iir;
  unsigned char lcr;
  unsigned char lcr;
  unsigned char mcr;
  unsigned char mcr;
  unsigned char lsr;
  unsigned char lsr;
  unsigned char msr;
  unsigned char msr;
  unsigned char div;
  unsigned char div;
  struct hw_event *event;
  struct hw_event *event;
};
};
 
 
/* UART registers.  */
/* UART registers.  */
 
 
#define LM32_UART_RBR           0x0
#define LM32_UART_RBR           0x0
#define LM32_UART_THR           0x0
#define LM32_UART_THR           0x0
#define LM32_UART_IER           0x4
#define LM32_UART_IER           0x4
#define LM32_UART_IIR           0x8
#define LM32_UART_IIR           0x8
#define LM32_UART_LCR           0xc
#define LM32_UART_LCR           0xc
#define LM32_UART_MCR           0x10
#define LM32_UART_MCR           0x10
#define LM32_UART_LSR           0x14
#define LM32_UART_LSR           0x14
#define LM32_UART_MSR           0x18
#define LM32_UART_MSR           0x18
#define LM32_UART_DIV           0x1c
#define LM32_UART_DIV           0x1c
 
 
#define LM32_UART_IER_RX_INT    0x1
#define LM32_UART_IER_RX_INT    0x1
#define LM32_UART_IER_TX_INT    0x2
#define LM32_UART_IER_TX_INT    0x2
 
 
#define MICOUART_IIR_TXRDY      0x2
#define MICOUART_IIR_TXRDY      0x2
#define MICOUART_IIR_RXRDY      0x4
#define MICOUART_IIR_RXRDY      0x4
 
 
#define LM32_UART_LSR_RX_RDY    0x01
#define LM32_UART_LSR_RX_RDY    0x01
#define LM32_UART_LSR_TX_RDY    0x20
#define LM32_UART_LSR_TX_RDY    0x20
 
 
#define LM32_UART_LCR_WLS_MASK  0x3
#define LM32_UART_LCR_WLS_MASK  0x3
#define LM32_UART_LCR_WLS_5     0x0
#define LM32_UART_LCR_WLS_5     0x0
#define LM32_UART_LCR_WLS_6     0x1
#define LM32_UART_LCR_WLS_6     0x1
#define LM32_UART_LCR_WLS_7     0x2
#define LM32_UART_LCR_WLS_7     0x2
#define LM32_UART_LCR_WLS_8     0x3
#define LM32_UART_LCR_WLS_8     0x3
 
 
/* UART ports.  */
/* UART ports.  */
 
 
enum
enum
{
{
  INT_PORT
  INT_PORT
};
};
 
 
static const struct hw_port_descriptor lm32uart_ports[] = {
static const struct hw_port_descriptor lm32uart_ports[] = {
  {"int", INT_PORT, 0, output_port},
  {"int", INT_PORT, 0, output_port},
  {}
  {}
};
};
 
 
static void
static void
do_uart_tx_event (struct hw *me, void *data)
do_uart_tx_event (struct hw *me, void *data)
{
{
  struct lm32uart *uart = hw_data (me);
  struct lm32uart *uart = hw_data (me);
  char c;
  char c;
 
 
  /* Generate interrupt when transmission is complete.  */
  /* Generate interrupt when transmission is complete.  */
  if (uart->ier & LM32_UART_IER_TX_INT)
  if (uart->ier & LM32_UART_IER_TX_INT)
    {
    {
      /* Generate interrupt */
      /* Generate interrupt */
      hw_port_event (me, INT_PORT, 1);
      hw_port_event (me, INT_PORT, 1);
    }
    }
 
 
  /* Indicate which interrupt has occured.  */
  /* Indicate which interrupt has occured.  */
  uart->iir = MICOUART_IIR_TXRDY;
  uart->iir = MICOUART_IIR_TXRDY;
 
 
  /* Indicate THR is empty.  */
  /* Indicate THR is empty.  */
  uart->lsr |= LM32_UART_LSR_TX_RDY;
  uart->lsr |= LM32_UART_LSR_TX_RDY;
 
 
  /* Output the character in the THR.  */
  /* Output the character in the THR.  */
  c = (char) uart->thr;
  c = (char) uart->thr;
 
 
  /* WLS field in LCR register specifies the number of bits to output.  */
  /* WLS field in LCR register specifies the number of bits to output.  */
  switch (uart->lcr & LM32_UART_LCR_WLS_MASK)
  switch (uart->lcr & LM32_UART_LCR_WLS_MASK)
    {
    {
    case LM32_UART_LCR_WLS_5:
    case LM32_UART_LCR_WLS_5:
      c &= 0x1f;
      c &= 0x1f;
      break;
      break;
    case LM32_UART_LCR_WLS_6:
    case LM32_UART_LCR_WLS_6:
      c &= 0x3f;
      c &= 0x3f;
      break;
      break;
    case LM32_UART_LCR_WLS_7:
    case LM32_UART_LCR_WLS_7:
      c &= 0x7f;
      c &= 0x7f;
      break;
      break;
    }
    }
  printf ("%c", c);
  printf ("%c", c);
}
}
 
 
static unsigned
static unsigned
lm32uart_io_write_buffer (struct hw *me,
lm32uart_io_write_buffer (struct hw *me,
                          const void *source,
                          const void *source,
                          int space, unsigned_word base, unsigned nr_bytes)
                          int space, unsigned_word base, unsigned nr_bytes)
{
{
  struct lm32uart *uart = hw_data (me);
  struct lm32uart *uart = hw_data (me);
  int uart_reg;
  int uart_reg;
  const unsigned char *source_bytes = source;
  const unsigned char *source_bytes = source;
  int value = 0;
  int value = 0;
 
 
  HW_TRACE ((me, "write to 0x%08lx length %d with 0x%x", (long) base,
  HW_TRACE ((me, "write to 0x%08lx length %d with 0x%x", (long) base,
             (int) nr_bytes, value));
             (int) nr_bytes, value));
 
 
  if (nr_bytes == 4)
  if (nr_bytes == 4)
    value = (source_bytes[0] << 24)
    value = (source_bytes[0] << 24)
      | (source_bytes[1] << 16) | (source_bytes[2] << 8) | (source_bytes[3]);
      | (source_bytes[1] << 16) | (source_bytes[2] << 8) | (source_bytes[3]);
  else
  else
    hw_abort (me, "write of unsupported number of bytes: %d.", nr_bytes);
    hw_abort (me, "write of unsupported number of bytes: %d.", nr_bytes);
 
 
  uart_reg = base - uart->base;
  uart_reg = base - uart->base;
 
 
  switch (uart_reg)
  switch (uart_reg)
    {
    {
    case LM32_UART_THR:
    case LM32_UART_THR:
      /* Buffer the character to output.  */
      /* Buffer the character to output.  */
      uart->thr = value;
      uart->thr = value;
 
 
      /* Indicate the THR is full.  */
      /* Indicate the THR is full.  */
      uart->lsr &= ~LM32_UART_LSR_TX_RDY;
      uart->lsr &= ~LM32_UART_LSR_TX_RDY;
 
 
      /* deassert interrupt when IER is loaded.  */
      /* deassert interrupt when IER is loaded.  */
      uart->iir &= ~MICOUART_IIR_TXRDY;
      uart->iir &= ~MICOUART_IIR_TXRDY;
 
 
      /* schedule an event to output the character.  */
      /* schedule an event to output the character.  */
      hw_event_queue_schedule (me, 1, do_uart_tx_event, 0);
      hw_event_queue_schedule (me, 1, do_uart_tx_event, 0);
 
 
      break;
      break;
    case LM32_UART_IER:
    case LM32_UART_IER:
      uart->ier = value;
      uart->ier = value;
      if ((value & LM32_UART_IER_TX_INT)
      if ((value & LM32_UART_IER_TX_INT)
          && (uart->lsr & LM32_UART_LSR_TX_RDY))
          && (uart->lsr & LM32_UART_LSR_TX_RDY))
        {
        {
          /* hw_event_queue_schedule (me, 1, do_uart_tx_event, 0); */
          /* hw_event_queue_schedule (me, 1, do_uart_tx_event, 0); */
          uart->lsr |= LM32_UART_LSR_TX_RDY;
          uart->lsr |= LM32_UART_LSR_TX_RDY;
          uart->iir |= MICOUART_IIR_TXRDY;
          uart->iir |= MICOUART_IIR_TXRDY;
          hw_port_event (me, INT_PORT, 1);
          hw_port_event (me, INT_PORT, 1);
        }
        }
      else if ((value & LM32_UART_IER_TX_INT) == 0)
      else if ((value & LM32_UART_IER_TX_INT) == 0)
        {
        {
          hw_port_event (me, INT_PORT, 0);
          hw_port_event (me, INT_PORT, 0);
        }
        }
      break;
      break;
    case LM32_UART_IIR:
    case LM32_UART_IIR:
      uart->iir = value;
      uart->iir = value;
      break;
      break;
    case LM32_UART_LCR:
    case LM32_UART_LCR:
      uart->lcr = value;
      uart->lcr = value;
      break;
      break;
    case LM32_UART_MCR:
    case LM32_UART_MCR:
      uart->mcr = value;
      uart->mcr = value;
      break;
      break;
    case LM32_UART_LSR:
    case LM32_UART_LSR:
      uart->lsr = value;
      uart->lsr = value;
      break;
      break;
    case LM32_UART_MSR:
    case LM32_UART_MSR:
      uart->msr = value;
      uart->msr = value;
      break;
      break;
    case LM32_UART_DIV:
    case LM32_UART_DIV:
      uart->div = value;
      uart->div = value;
      break;
      break;
    default:
    default:
      hw_abort (me, "write to invalid register address: 0x%x.", uart_reg);
      hw_abort (me, "write to invalid register address: 0x%x.", uart_reg);
    }
    }
 
 
  return nr_bytes;
  return nr_bytes;
}
}
 
 
static unsigned
static unsigned
lm32uart_io_read_buffer (struct hw *me,
lm32uart_io_read_buffer (struct hw *me,
                         void *dest,
                         void *dest,
                         int space, unsigned_word base, unsigned nr_bytes)
                         int space, unsigned_word base, unsigned nr_bytes)
{
{
  struct lm32uart *uart = hw_data (me);
  struct lm32uart *uart = hw_data (me);
  int uart_reg;
  int uart_reg;
  int value;
  int value;
  unsigned char *dest_bytes = dest;
  unsigned char *dest_bytes = dest;
  fd_set fd;
  fd_set fd;
  struct timeval tv;
  struct timeval tv;
 
 
  HW_TRACE ((me, "read 0x%08lx length %d", (long) base, (int) nr_bytes));
  HW_TRACE ((me, "read 0x%08lx length %d", (long) base, (int) nr_bytes));
 
 
  uart_reg = base - uart->base;
  uart_reg = base - uart->base;
 
 
  switch (uart_reg)
  switch (uart_reg)
    {
    {
    case LM32_UART_RBR:
    case LM32_UART_RBR:
      value = getchar ();
      value = getchar ();
      uart->lsr &= ~LM32_UART_LSR_RX_RDY;
      uart->lsr &= ~LM32_UART_LSR_RX_RDY;
      break;
      break;
    case LM32_UART_IER:
    case LM32_UART_IER:
      value = uart->ier;
      value = uart->ier;
      break;
      break;
    case LM32_UART_IIR:
    case LM32_UART_IIR:
      value = uart->iir;
      value = uart->iir;
      break;
      break;
    case LM32_UART_LCR:
    case LM32_UART_LCR:
      value = uart->lcr;
      value = uart->lcr;
      break;
      break;
    case LM32_UART_MCR:
    case LM32_UART_MCR:
      value = uart->mcr;
      value = uart->mcr;
      break;
      break;
    case LM32_UART_LSR:
    case LM32_UART_LSR:
      /* Check to see if any data waiting in stdin.  */
      /* Check to see if any data waiting in stdin.  */
      FD_ZERO (&fd);
      FD_ZERO (&fd);
      FD_SET (fileno (stdin), &fd);
      FD_SET (fileno (stdin), &fd);
      tv.tv_sec = 0;
      tv.tv_sec = 0;
      tv.tv_usec = 1;
      tv.tv_usec = 1;
      if (select (fileno (stdin) + 1, &fd, NULL, NULL, &tv))
      if (select (fileno (stdin) + 1, &fd, NULL, NULL, &tv))
        uart->lsr |= LM32_UART_LSR_RX_RDY;
        uart->lsr |= LM32_UART_LSR_RX_RDY;
      value = uart->lsr;
      value = uart->lsr;
      break;
      break;
    case LM32_UART_MSR:
    case LM32_UART_MSR:
      value = uart->msr;
      value = uart->msr;
      break;
      break;
    case LM32_UART_DIV:
    case LM32_UART_DIV:
      value = uart->div;
      value = uart->div;
      break;
      break;
    default:
    default:
      hw_abort (me, "read from invalid register address: 0x%x.", uart_reg);
      hw_abort (me, "read from invalid register address: 0x%x.", uart_reg);
    }
    }
 
 
  if (nr_bytes == 4)
  if (nr_bytes == 4)
    {
    {
      dest_bytes[0] = value >> 24;
      dest_bytes[0] = value >> 24;
      dest_bytes[1] = value >> 16;
      dest_bytes[1] = value >> 16;
      dest_bytes[2] = value >> 8;
      dest_bytes[2] = value >> 8;
      dest_bytes[3] = value;
      dest_bytes[3] = value;
    }
    }
  else
  else
    hw_abort (me, "read of unsupported number of bytes: %d", nr_bytes);
    hw_abort (me, "read of unsupported number of bytes: %d", nr_bytes);
 
 
  return nr_bytes;
  return nr_bytes;
}
}
 
 
static void
static void
attach_lm32uart_regs (struct hw *me, struct lm32uart *uart)
attach_lm32uart_regs (struct hw *me, struct lm32uart *uart)
{
{
  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_address, me);
                                     &attach_space, &attach_address, me);
  uart->base = attach_address;
  uart->base = attach_address;
  hw_unit_size_to_attach_size (hw_parent (me), &reg.size, &attach_size, me);
  hw_unit_size_to_attach_size (hw_parent (me), &reg.size, &attach_size, me);
  uart->limit = attach_address + (attach_size - 1);
  uart->limit = attach_address + (attach_size - 1);
  hw_attach_address (hw_parent (me),
  hw_attach_address (hw_parent (me),
                     0, attach_space, attach_address, attach_size, me);
                     0, attach_space, attach_address, attach_size, me);
}
}
 
 
static void
static void
lm32uart_finish (struct hw *me)
lm32uart_finish (struct hw *me)
{
{
  struct lm32uart *uart;
  struct lm32uart *uart;
  int i;
  int i;
 
 
  uart = HW_ZALLOC (me, struct lm32uart);
  uart = HW_ZALLOC (me, struct lm32uart);
  set_hw_data (me, uart);
  set_hw_data (me, uart);
  set_hw_io_read_buffer (me, lm32uart_io_read_buffer);
  set_hw_io_read_buffer (me, lm32uart_io_read_buffer);
  set_hw_io_write_buffer (me, lm32uart_io_write_buffer);
  set_hw_io_write_buffer (me, lm32uart_io_write_buffer);
  set_hw_ports (me, lm32uart_ports);
  set_hw_ports (me, lm32uart_ports);
 
 
  /* Attach ourself to our parent bus.  */
  /* Attach ourself to our parent bus.  */
  attach_lm32uart_regs (me, uart);
  attach_lm32uart_regs (me, uart);
 
 
  /* Initialize the UART.  */
  /* Initialize the UART.  */
  uart->rbr = 0;
  uart->rbr = 0;
  uart->thr = 0;
  uart->thr = 0;
  uart->ier = 0;
  uart->ier = 0;
  uart->iir = 0;
  uart->iir = 0;
  uart->lcr = 0;
  uart->lcr = 0;
  uart->mcr = 0;
  uart->mcr = 0;
  uart->lsr = LM32_UART_LSR_TX_RDY;
  uart->lsr = LM32_UART_LSR_TX_RDY;
  uart->msr = 0;
  uart->msr = 0;
  uart->div = 0;         /* By setting to zero, characters are output immediately.  */
  uart->div = 0;         /* By setting to zero, characters are output immediately.  */
}
}
 
 
const struct hw_descriptor dv_lm32uart_descriptor[] = {
const struct hw_descriptor dv_lm32uart_descriptor[] = {
  {"lm32uart", lm32uart_finish,},
  {"lm32uart", lm32uart_finish,},
  {NULL},
  {NULL},
};
};
 
 

powered by: WebSVN 2.1.0

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