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

Subversion Repositories or1k

[/] [or1k/] [tags/] [nog_patch_70/] [or1ksim/] [peripheral/] [16450.c] - Diff between revs 1366 and 1367

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 1366 Rev 1367
Line 48... Line 48...
#include "channel.h"
#include "channel.h"
#include "debug.h"
#include "debug.h"
 
 
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#define MIN(a,b) ((a) < (b) ? (a) : (b))
 
 
static struct dev_16450 uarts[MAX_UARTS];                       /* simulation info */
 
static struct channel * channels[MAX_UARTS] = { NULL, };        /* emulation info */
 
 
 
/* Number of clock cycles (one clock cycle is one call to the uart_clock())
/* Number of clock cycles (one clock cycle is one call to the uart_clock())
   before a single character is transmitted or received. */
   before a single character is transmitted or received. */
static unsigned long char_clks(int dll, int dlh, int lcr)
static unsigned long char_clks(int dll, int dlh, int lcr)
{
{
  float bauds_per_char = 1.;
  float bauds_per_char = 1.;
Line 78... Line 75...
}
}
 
 
/* Set a specific UART register with value. */
/* Set a specific UART register with value. */
void uart_write_byte(oraddr_t addr, uint32_t value, void *dat)
void uart_write_byte(oraddr_t addr, uint32_t value, void *dat)
{
{
  int chipsel;
  struct dev_16450 *uart = dat;
 
 
  debug(4, "uart_write_byte(%"PRIxADDR",%02"PRIx32")\n", addr, value);
  debug(4, "uart_write_byte(%"PRIxADDR",%02"PRIx32")\n", addr, value);
 
 
  for(chipsel = 0; chipsel < MAX_UARTS; chipsel++)
  if (uart->regs.lcr & UART_LCR_DLAB) {
    if ((addr & ~(UART_ADDR_SPACE-1)) == config.uarts[chipsel].baseaddr)
 
      break;
 
  if (chipsel >= MAX_UARTS) return;
 
 
 
  if (uarts[chipsel].regs.lcr & UART_LCR_DLAB) {
 
    switch (addr % UART_ADDR_SPACE) {
    switch (addr % UART_ADDR_SPACE) {
      case UART_DLL:
      case UART_DLL:
        uarts[chipsel].regs.dll = value;
        uart->regs.dll = value;
        uarts[chipsel].char_clks = char_clks(uarts[chipsel].regs.dll, uarts[chipsel].regs.dlh, uarts[chipsel].regs.lcr);
        uart->char_clks = char_clks(uart->regs.dll, uart->regs.dlh, uart->regs.lcr);
        return;
        return;
      case UART_DLH:
      case UART_DLH:
        uarts[chipsel].regs.dlh = value;
        uart->regs.dlh = value;
        return;
        return;
    }
    }
  }
  }
 
 
  switch (addr % UART_ADDR_SPACE) {
  switch (addr % UART_ADDR_SPACE) {
    case UART_TXBUF:
    case UART_TXBUF:
      if (uarts[chipsel].istat.txbuf_full < uarts[chipsel].fifo_len) {
      if (uart->istat.txbuf_full < uart->fifo_len) {
        uarts[chipsel].istat.txbuf_full++;
        uart->istat.txbuf_full++;
        uarts[chipsel].regs.txbuf[uarts[chipsel].istat.txbuf_head] = value;
        uart->regs.txbuf[uart->istat.txbuf_head] = value;
        uarts[chipsel].istat.txbuf_head = (uarts[chipsel].istat.txbuf_head + 1) % uarts[chipsel].fifo_len;
        uart->istat.txbuf_head = (uart->istat.txbuf_head + 1) % uart->fifo_len;
      } else
      } else
        uarts[chipsel].regs.txbuf[uarts[chipsel].istat.txbuf_head] = value;
        uart->regs.txbuf[uart->istat.txbuf_head] = value;
 
 
      uarts[chipsel].regs.lsr &= ~(UART_LSR_TXSERE | UART_LSR_TXBUFE);
      uart->regs.lsr &= ~(UART_LSR_TXSERE | UART_LSR_TXBUFE);
      if (uarts[chipsel].regs.iir & UART_IIR_THRI)
      if (uart->regs.iir & UART_IIR_THRI)
        uarts[chipsel].istat.thre_int = 0;
        uart->istat.thre_int = 0;
      break;
      break;
    case UART_FCR:
    case UART_FCR:
      uarts[chipsel].regs.fcr = value & UART_VALID_FCR;
      uart->regs.fcr = value & UART_VALID_FCR;
      if (uarts[chipsel].fifo_len == 1 && (value & UART_FCR_FIE)
      if ((uart->fifo_len == 1 && (value & UART_FCR_FIE))
       || uarts[chipsel].fifo_len != 1 && !(value & UART_FCR_FIE))
       || (uart->fifo_len != 1 && !(value & UART_FCR_FIE)))
        value |= UART_FCR_RRXFI | UART_FCR_RTXFI;
        value |= UART_FCR_RRXFI | UART_FCR_RTXFI;
      uarts[chipsel].fifo_len = (value & UART_FCR_FIE) ? 16 : 1;
      uart->fifo_len = (value & UART_FCR_FIE) ? 16 : 1;
      if (value & UART_FCR_RTXFI) {
      if (value & UART_FCR_RTXFI) {
        uarts[chipsel].istat.txbuf_head = uarts[chipsel].istat.txbuf_tail = 0;
        uart->istat.txbuf_head = uart->istat.txbuf_tail = 0;
        uarts[chipsel].istat.txbuf_full = 0;
        uart->istat.txbuf_full = 0;
        uarts[chipsel].regs.lsr |= UART_LSR_TXBUFE;
        uart->regs.lsr |= UART_LSR_TXBUFE;
 
 
        // For FIFO-mode only, THRE interrupt is set when THR and FIFO are empty
        // For FIFO-mode only, THRE interrupt is set when THR and FIFO are empty
        uarts[chipsel].istat.thre_int = (uarts[chipsel].fifo_len == 16);
        uart->istat.thre_int = (uart->fifo_len == 16);
      }
      }
      if (value & UART_FCR_RRXFI) {
      if (value & UART_FCR_RRXFI) {
        uarts[chipsel].istat.rxbuf_head = uarts[chipsel].istat.rxbuf_tail = 0;
        uart->istat.rxbuf_head = uart->istat.rxbuf_tail = 0;
        uarts[chipsel].istat.rxbuf_full = 0;
        uart->istat.rxbuf_full = 0;
        uarts[chipsel].regs.lsr &= ~UART_LSR_RDRDY;
        uart->regs.lsr &= ~UART_LSR_RDRDY;
      }
      }
      break;
      break;
    case UART_IER:
    case UART_IER:
      uarts[chipsel].regs.ier = value & UART_VALID_IER;
      uart->regs.ier = value & UART_VALID_IER;
      break;
      break;
    case UART_LCR:
    case UART_LCR:
      uarts[chipsel].regs.lcr = value & UART_VALID_LCR;
      uart->regs.lcr = value & UART_VALID_LCR;
      uarts[chipsel].char_clks = char_clks(uarts[chipsel].regs.dll, uarts[chipsel].regs.dlh, uarts[chipsel].regs.lcr);
      uart->char_clks = char_clks(uart->regs.dll, uart->regs.dlh, uart->regs.lcr);
      break;
      break;
    case UART_MCR:
    case UART_MCR:
      uarts[chipsel].regs.mcr = value & UART_VALID_MCR;
      uart->regs.mcr = value & UART_VALID_MCR;
      break;
      break;
    case UART_SCR:
    case UART_SCR:
      uarts[chipsel].regs.scr = value;
      uart->regs.scr = value;
      break;
      break;
    default:
    default:
      debug(1, "write out of range (addr %x)\n", addr);
      debug(1, "write out of range (addr %x)\n", addr);
  }
  }
}
}
 
 
/* Read a specific UART register. */
/* Read a specific UART register. */
uint32_t uart_read_byte(oraddr_t addr, void *dat)
uint32_t uart_read_byte(oraddr_t addr, void *dat)
{
{
 
  struct dev_16450 *uart = dat;
  uint8_t value = 0;
  uint8_t value = 0;
  int chipsel;
 
 
 
  debug(4, "uart_read_byte(%"PRIxADDR")", addr);
  debug(4, "uart_read_byte(%"PRIxADDR")", addr);
 
 
  for(chipsel = 0; chipsel < MAX_UARTS; chipsel++)
  if (uart->regs.lcr & UART_LCR_DLAB) {
    if ((addr & ~(UART_ADDR_SPACE-1)) == config.uarts[chipsel].baseaddr)
 
      break;
 
 
 
  if (chipsel >= MAX_UARTS)
 
    return 0;
 
 
 
  if (uarts[chipsel].regs.lcr & UART_LCR_DLAB) {
 
    switch (addr % UART_ADDR_SPACE) {
    switch (addr % UART_ADDR_SPACE) {
      case UART_DLL:
      case UART_DLL:
        value = uarts[chipsel].regs.dll;
        value = uart->regs.dll;
        debug(4, "= %"PRIx8"\n", value);
        debug(4, "= %"PRIx8"\n", value);
        return value;
        return value;
      case UART_DLH:
      case UART_DLH:
        value = uarts[chipsel].regs.dlh;
        value = uart->regs.dlh;
        debug(4, "= %"PRIx8"\n", value);
        debug(4, "= %"PRIx8"\n", value);
        return value;
        return value;
    }
    }
  }
  }
 
 
  switch (addr % UART_ADDR_SPACE) {
  switch (addr % UART_ADDR_SPACE) {
    case UART_RXBUF:
    case UART_RXBUF:
      { /* Print out FIFO for debugging */
      { /* Print out FIFO for debugging */
        int i;
        int i;
        debug(4, "(%i/%i,%i,%i:", uarts[chipsel].istat.rxbuf_full, uarts[chipsel].fifo_len,
        debug(4, "(%i/%i,%i,%i:", uart->istat.rxbuf_full, uart->fifo_len,
                  uarts[chipsel].istat.rxbuf_head, uarts[chipsel].istat.rxbuf_tail);
                  uart->istat.rxbuf_head, uart->istat.rxbuf_tail);
        for (i = 0; i < uarts[chipsel].istat.rxbuf_full; i++)
        for (i = 0; i < uart->istat.rxbuf_full; i++)
          debug(4, "%02x ", uarts[chipsel].regs.rxbuf[(uarts[chipsel].istat.rxbuf_tail + i) % uarts[chipsel].fifo_len]);
          debug(4, "%02x ", uart->regs.rxbuf[(uart->istat.rxbuf_tail + i) % uart->fifo_len]);
        debug(4, ")");
        debug(4, ")");
      }
      }
      if (uarts[chipsel].istat.rxbuf_full) {
      if (uart->istat.rxbuf_full) {
        value = uarts[chipsel].regs.rxbuf[uarts[chipsel].istat.rxbuf_tail];
        value = uart->regs.rxbuf[uart->istat.rxbuf_tail];
        uarts[chipsel].istat.rxbuf_tail = (uarts[chipsel].istat.rxbuf_tail + 1) % uarts[chipsel].fifo_len;
        uart->istat.rxbuf_tail = (uart->istat.rxbuf_tail + 1) % uart->fifo_len;
        uarts[chipsel].istat.rxbuf_full--;
        uart->istat.rxbuf_full--;
      }
      }
 
 
      if (uarts[chipsel].istat.rxbuf_full)
      if (uart->istat.rxbuf_full)
        uarts[chipsel].regs.lsr |= UART_LSR_RDRDY;
        uart->regs.lsr |= UART_LSR_RDRDY;
      else
      else
        uarts[chipsel].regs.lsr &= ~UART_LSR_RDRDY;
        uart->regs.lsr &= ~UART_LSR_RDRDY;
 
 
      uarts[chipsel].istat.timeout_count = 0;
      uart->istat.timeout_count = 0;
      break;
      break;
    case UART_IER:
    case UART_IER:
      value = uarts[chipsel].regs.ier & UART_VALID_IER;
      value = uart->regs.ier & UART_VALID_IER;
      break;
      break;
    case UART_IIR:
    case UART_IIR:
      value = (uarts[chipsel].regs.iir & UART_VALID_IIR) | 0xc0;
      value = (uart->regs.iir & UART_VALID_IIR) | 0xc0;
      if (uarts[chipsel].regs.iir & UART_IIR_THRI)
      if (uart->regs.iir & UART_IIR_THRI)
        uarts[chipsel].istat.thre_int = 0;
        uart->istat.thre_int = 0;
      break;
      break;
    case UART_LCR:
    case UART_LCR:
      value = uarts[chipsel].regs.lcr & UART_VALID_LCR;
      value = uart->regs.lcr & UART_VALID_LCR;
      break;
      break;
    case UART_MCR:
    case UART_MCR:
      value = 0;
      value = 0;
      break;
      break;
    case UART_LSR:
    case UART_LSR:
      value = uarts[chipsel].regs.lsr & UART_VALID_LSR;
      value = uart->regs.lsr & UART_VALID_LSR;
      uarts[chipsel].regs.lsr &=
      uart->regs.lsr &=
        ~(UART_LSR_OVRRUN | UART_LSR_BREAK | UART_LSR_PARITY
        ~(UART_LSR_OVRRUN | UART_LSR_BREAK | UART_LSR_PARITY
         | UART_LSR_FRAME | UART_LSR_RXERR);
         | UART_LSR_FRAME | UART_LSR_RXERR);
      break;
      break;
    case UART_MSR:
    case UART_MSR:
      value = uarts[chipsel].regs.msr & UART_VALID_MSR;
      value = uart->regs.msr & UART_VALID_MSR;
      uarts[chipsel].regs.msr = 0;
      uart->regs.msr = 0;
      break;
      break;
    case UART_SCR:
    case UART_SCR:
      value = uarts[chipsel].regs.scr;
      value = uart->regs.scr;
      break;
      break;
    default:
    default:
      debug(1, "read out of range (addr %"PRIxADDR")\n", addr);
      debug(1, "read out of range (addr %"PRIxADDR")\n", addr);
  }
  }
  debug(4, " = %"PRIx8"\n", value);
  debug(4, " = %"PRIx8"\n", value);
Line 238... Line 223...
}
}
 
 
/* Function that handles incoming VAPI data.  */
/* Function that handles incoming VAPI data.  */
void uart_vapi_read (unsigned long id, unsigned long data, void *dat)
void uart_vapi_read (unsigned long id, unsigned long data, void *dat)
{
{
  int uart;
  struct dev_16450 *uart = dat;
  debug(4, "UART: id %08lx, data %08lx\n", id, data);
  debug(4, "UART: id %08lx, data %08lx\n", id, data);
  uart = id & VAPI_DEVICE_ID;
  uart->vapi_buf[uart->vapi_buf_head_ptr] = data;
  uarts[uart].vapi_buf[uarts[uart].vapi_buf_head_ptr] = data;
  uart->vapi_buf_head_ptr = (uart->vapi_buf_head_ptr + 1) % UART_VAPI_BUF_LEN;
  uarts[uart].vapi_buf_head_ptr = (uarts[uart].vapi_buf_head_ptr + 1) % UART_VAPI_BUF_LEN;
  if (uart->vapi_buf_tail_ptr == uart->vapi_buf_head_ptr) {
  if (uarts[uart].vapi_buf_tail_ptr == uarts[uart].vapi_buf_head_ptr) {
 
    fprintf (stderr, "FATAL: uart VAPI buffer to small.\n");
    fprintf (stderr, "FATAL: uart VAPI buffer to small.\n");
    exit (1);
    exit (1);
  }
  }
}
}
 
 
static void send_char (int uart, int bits_send)
static void send_char (struct dev_16450 *uart, int bits_send)
{
{
  PRINTF ("%c", (char)uarts[uart].iregs.txser);
  PRINTF ("%c", (char)uart->iregs.txser);
  debug(4, "TX \'%c\' via UART%d...\n", (char)uarts[uart].iregs.txser, uart);
  debug(4, "TX \'%c\' via UART at %"PRIxADDR"...\n", (char)uart->iregs.txser,
  if (uarts[uart].regs.mcr & UART_MCR_LOOP)
        uart->baseaddr);
    uarts[uart].iregs.loopback = uarts[uart].iregs.txser;
  if (uart->regs.mcr & UART_MCR_LOOP)
 
    uart->iregs.loopback = uart->iregs.txser;
  else {
  else {
    /* Send to either VAPI or to file */
    /* Send to either VAPI or to file */
    if (config.uarts[uart].vapi_id) {
    if (uart->vapi_id) {
      int par, pe, fe, nbits;
      int par, pe, fe, nbits;
      int j, data;
      int j, data;
      unsigned long packet = 0;
      unsigned long packet = 0;
 
 
      nbits = MIN (bits_send, (uarts[uart].regs.lcr & UART_LCR_WLEN8) + 5);
      nbits = MIN (bits_send, (uart->regs.lcr & UART_LCR_WLEN8) + 5);
      /* Encode a packet */
      /* Encode a packet */
      packet = uarts[uart].iregs.txser & ((1 << nbits) - 1);
      packet = uart->iregs.txser & ((1 << nbits) - 1);
 
 
      /* Calculate parity */
      /* Calculate parity */
      for (j = 0, par = 0; j < nbits; j++)
      for (j = 0, par = 0; j < nbits; j++)
        par ^= (packet >> j) & 1;
        par ^= (packet >> j) & 1;
 
 
      if (uarts[uart].regs.lcr & UART_LCR_PARITY) {
      if (uart->regs.lcr & UART_LCR_PARITY) {
        if (uarts[uart].regs.lcr & UART_LCR_SPAR) {
        if (uart->regs.lcr & UART_LCR_SPAR) {
          packet |= 1 << nbits;
          packet |= 1 << nbits;
        } else {
        } else {
          if (uarts[uart].regs.lcr & UART_LCR_EPAR)
          if (uart->regs.lcr & UART_LCR_EPAR)
            packet |= par << nbits;
            packet |= par << nbits;
          else
          else
            packet |= (par ^ 1) << nbits;
            packet |= (par ^ 1) << nbits;
        }
        }
        nbits++;
        nbits++;
      }
      }
      packet |= 1 << (nbits++);
      packet |= 1 << (nbits++);
      if (uarts[uart].regs.lcr & UART_LCR_STOP)
      if (uart->regs.lcr & UART_LCR_STOP)
        packet |= 1 << (nbits++);
        packet |= 1 << (nbits++);
 
 
      /* Decode a packet */
      /* Decode a packet */
      nbits = (uarts[uart].vapi.lcr & UART_LCR_WLEN8) + 5;
      nbits = (uart->vapi.lcr & UART_LCR_WLEN8) + 5;
      data = packet & ((1 << nbits) - 1);
      data = packet & ((1 << nbits) - 1);
 
 
      /* Calculate parity, including parity bit */
      /* Calculate parity, including parity bit */
      for (j = 0, par = 0; j < nbits + 1; j++)
      for (j = 0, par = 0; j < nbits + 1; j++)
        par ^= (packet >> j) & 1;
        par ^= (packet >> j) & 1;
 
 
      if (uarts[uart].vapi.lcr & UART_LCR_PARITY) {
      if (uart->vapi.lcr & UART_LCR_PARITY) {
        if (uarts[uart].vapi.lcr & UART_LCR_SPAR) {
        if (uart->vapi.lcr & UART_LCR_SPAR) {
          pe = !((packet >> nbits) & 1);
          pe = !((packet >> nbits) & 1);
        } else {
        } else {
          if (uarts[uart].vapi.lcr & UART_LCR_EPAR)
          if (uart->vapi.lcr & UART_LCR_EPAR)
            pe = par != 0;
            pe = par != 0;
          else
          else
            pe = par != 1;
            pe = par != 1;
        }
        }
        nbits++;
        nbits++;
      } else
      } else
        pe = 0;
        pe = 0;
 
 
      fe = ((packet >> (nbits++)) & 1) ^ 1;
      fe = ((packet >> (nbits++)) & 1) ^ 1;
      if (uarts[uart].vapi.lcr & UART_LCR_STOP)
      if (uart->vapi.lcr & UART_LCR_STOP)
        fe |= ((packet >> (nbits++)) & 1) ^ 1;
        fe |= ((packet >> (nbits++)) & 1) ^ 1;
 
 
      debug (4, "lcr vapi %02x, uart %02x\n", uarts[uart].vapi.lcr, uarts[uart].regs.lcr);
      debug (4, "lcr vapi %02x, uart %02x\n", uart->vapi.lcr, uart->regs.lcr);
      data |= (uarts[uart].vapi.lcr << 8) | (pe << 16) | (fe << 17) | (uarts[uart].vapi.lcr << 8);
      data |= (uart->vapi.lcr << 8) | (pe << 16) | (fe << 17) | (uart->vapi.lcr << 8);
      PRINTF ("vapi_send (%08lx, %08x)\n", config.uarts[uart].vapi_id, data);
      PRINTF ("vapi_send (%08lx, %08x)\n", uart->vapi_id, data);
      debug (4, "vapi_send (%08lx, %08x)\n", config.uarts[uart].vapi_id, data);
      debug (4, "vapi_send (%08lx, %08x)\n", uart->vapi_id, data);
      vapi_send (config.uarts[uart].vapi_id, data);
      vapi_send (uart->vapi_id, data);
    } else {
    } else {
      char buffer[1] = { uarts[uart].iregs.txser & 0xFF };
      char buffer[1] = { uart->iregs.txser & 0xFF };
      channel_write(channels[uart], buffer, 1);
      channel_write(uart->channel, buffer, 1);
    }
    }
  }
  }
  uarts[uart].istat.txser_full = 0;
  uart->istat.txser_full = 0;
  uarts[uart].istat.txser_clks = 0;
  uart->istat.txser_clks = 0;
}
}
 
 
/* Adds a character to the FIFO */
/* Adds a character to the FIFO */
 
 
void uart_add_char (int uart, int ch)
void uart_add_char (struct dev_16450 *uart, int ch)
{
{
  if (uarts[uart].istat.rxbuf_full + 1 > uarts[uart].fifo_len)
  if (uart->istat.rxbuf_full + 1 > uart->fifo_len)
    uarts[uart].regs.lsr |= UART_LSR_OVRRUN | UART_LSR_RXERR;
    uart->regs.lsr |= UART_LSR_OVRRUN | UART_LSR_RXERR;
  else {
  else {
    debug(4, "add %02x\n", ch);
    debug(4, "add %02x\n", ch);
    uarts[uart].regs.rxbuf[uarts[uart].istat.rxbuf_head] = ch;
    uart->regs.rxbuf[uart->istat.rxbuf_head] = ch;
    uarts[uart].istat.rxbuf_head = (uarts[uart].istat.rxbuf_head + 1) % uarts[uart].fifo_len;
    uart->istat.rxbuf_head = (uart->istat.rxbuf_head + 1) % uart->fifo_len;
    uarts[uart].istat.rxbuf_full++;
    uart->istat.rxbuf_full++;
  }
  }
  uarts[uart].regs.lsr |= UART_LSR_RDRDY;
  uart->regs.lsr |= UART_LSR_RDRDY;
  uarts[uart].istat.timeout_count = 0;
  uart->istat.timeout_count = 0;
}
}
 
 
/* Simulation hook. Must be called every clock cycle to simulate all UART
/* Simulation hook. Must be called every clock cycle to simulate all UART
   devices. It does internal functional UART simulation. */
   devices. It does internal functional UART simulation. */
void uart_clock16 (int i)
void uart_clock16 (void *dat)
{
{
 
  struct dev_16450 *uart = dat;
  int retval;
  int retval;
 
 
  /* Schedule for later */
  /* Schedule for later */
  SCHED_ADD (uart_clock16, i, runtime.sim.cycles + UART_CLOCK_DIVIDER);
  SCHED_ADD (uart_clock16, dat, runtime.sim.cycles + UART_CLOCK_DIVIDER);
 
 
  /* If VAPI is not selected, UART communicates with two file streams;
  /* If VAPI is not selected, UART communicates with two file streams;
     if VAPI is selected, we use VAPI streams.  */
     if VAPI is selected, we use VAPI streams.  */
  /* if txfs is corrupted, skip this uart. */
  /* if txfs is corrupted, skip this uart. */
  if (!config.uarts[i].vapi_id && !channel_ok(channels[i])) return;
  if (!uart->vapi_id && !channel_ok(uart->channel)) return;
 
 
  if (uarts[i].vapi.next_break_cnt >= 0)
  if (uart->vapi.next_break_cnt >= 0)
    if (--uarts[i].vapi.next_break_cnt < 0) {
    if (--uart->vapi.next_break_cnt < 0) {
      if (!(uarts[i].vapi.cur_break = uarts[i].vapi.next_break))
      if (!(uart->vapi.cur_break = uart->vapi.next_break))
        uarts[i].istat.break_set = 0;
        uart->istat.break_set = 0;
    }
    }
 
 
  /***************** Transmit *****************/
  /***************** Transmit *****************/
  if (!uarts[i].istat.txser_full) {
  if (!uart->istat.txser_full) {
//      uarts[i].regs.lsr |= UART_LSR_TXBUFE;
//      uart->regs.lsr |= UART_LSR_TXBUFE;
    if (uarts[i].istat.txbuf_full) {
    if (uart->istat.txbuf_full) {
      uarts[i].iregs.txser = uarts[i].regs.txbuf[uarts[i].istat.txbuf_tail];
      uart->iregs.txser = uart->regs.txbuf[uart->istat.txbuf_tail];
      uarts[i].istat.txbuf_tail = (uarts[i].istat.txbuf_tail + 1) % uarts[i].fifo_len;
      uart->istat.txbuf_tail = (uart->istat.txbuf_tail + 1) % uart->fifo_len;
      uarts[i].istat.txser_full = 1;
      uart->istat.txser_full = 1;
      uarts[i].istat.txbuf_full--;
      uart->istat.txbuf_full--;
      uarts[i].regs.lsr &= ~UART_LSR_TXSERE;
      uart->regs.lsr &= ~UART_LSR_TXSERE;
 
 
      // When UART is in either character mode, i.e. 16450 emulation mode, or FIFO mode,
      // When UART is in either character mode, i.e. 16450 emulation mode, or FIFO mode,
      // the THRE interrupt is raised when THR transitions from full to empty.
      // the THRE interrupt is raised when THR transitions from full to empty.
      if (!uarts[i].istat.txbuf_full) {
      if (!uart->istat.txbuf_full) {
        uarts[i].istat.thre_int = 1;
        uart->istat.thre_int = 1;
        uarts[i].regs.lsr |= UART_LSR_TXBUFE;
        uart->regs.lsr |= UART_LSR_TXBUFE;
      }
      }
    } else {
    } else {
      uarts[i].regs.lsr |= UART_LSR_TXSERE;
      uart->regs.lsr |= UART_LSR_TXSERE;
    }
    }
  } else if (uarts[i].char_clks <= uarts[i].istat.txser_clks++) {
  } else if (uart->char_clks <= uart->istat.txser_clks++) {
    send_char(i, (uarts[i].regs.lcr & UART_LCR_WLEN8) + 5); /* We've sent all bits */
    send_char(uart, (uart->regs.lcr & UART_LCR_WLEN8) + 5); /* We've sent all bits */
  } else {
  } else {
    /* We are still sending char here*/
    /* We are still sending char here*/
 
 
    /* Check if we set the break bit */
    /* Check if we set the break bit */
    if (uarts[i].regs.lcr & UART_LCR_SBC) {
    if (uart->regs.lcr & UART_LCR_SBC) {
      if (!uarts[i].vapi.break_sent) {
      if (!uart->vapi.break_sent) {
#if 0
#if 0
        /* Send broken frame */
        /* Send broken frame */
        int nbits_sent = ((uarts[i].regs.lcr & UART_LCR_WLEN8) + 5) * (uarts[i].istat.txser_clks - 1) / uarts[i].char_clks;
        int nbits_sent = ((uart->regs.lcr & UART_LCR_WLEN8) + 5) * (uart->istat.txser_clks - 1) / uart->char_clks;
        send_char(i, nbits_sent);
        send_char(i, nbits_sent);
#endif
#endif
        /* Send one break signal */
        /* Send one break signal */
        vapi_send (config.uarts[i].vapi_id, UART_LCR_SBC << 8);
        vapi_send (uart->vapi_id, UART_LCR_SBC << 8);
        uarts[i].vapi.break_sent = 1;
        uart->vapi.break_sent = 1;
      }
      }
      /* mark as character was sent */
      /* mark as character was sent */
      uarts[i].istat.txser_full = 0;
      uart->istat.txser_full = 0;
      uarts[i].istat.txser_clks = 0;
      uart->istat.txser_clks = 0;
    } else
    } else
      uarts[i].vapi.break_sent = 0;
      uart->vapi.break_sent = 0;
 
 
  }
  }
 
 
  /***************** Receive *****************/
  /***************** Receive *****************/
 
 
  /* Is there a break? */
  /* Is there a break? */
  if (uarts[i].vapi.cur_break) {
  if (uart->vapi.cur_break) {
    uarts[i].vapi.cur_break_cnt++;
    uart->vapi.cur_break_cnt++;
    if (uarts[i].vapi.cur_break_cnt > UART_BREAK_COUNT * uarts[i].vapi.char_clks) {
    if (uart->vapi.cur_break_cnt > UART_BREAK_COUNT * uart->vapi.char_clks) {
      if (!uarts[i].istat.break_set) {
      if (!uart->istat.break_set) {
        unsigned lsr;
        unsigned lsr;
        uarts[i].istat.break_set = 1;
        uart->istat.break_set = 1;
        lsr = UART_LSR_BREAK | UART_LSR_RXERR | UART_LSR_RDRDY;
        lsr = UART_LSR_BREAK | UART_LSR_RXERR | UART_LSR_RDRDY;
        PRINTF ("[%x]\n", uarts[i].regs.lsr);
        PRINTF ("[%x]\n", uart->regs.lsr);
        uarts[i].istat.rxser_full = 0;
        uart->istat.rxser_full = 0;
        uarts[i].istat.rxser_clks = 0;
        uart->istat.rxser_clks = 0;
        uart_add_char (i, lsr << 8);
        uart_add_char (uart, lsr << 8);
      } else
      } else
        uarts[i].vapi.cur_break_cnt = 0;
        uart->vapi.cur_break_cnt = 0;
    }
    }
    if (uarts[i].istat.rxser_full) {
    if (uart->istat.rxser_full) {
      uarts[i].istat.rxser_full = 0;
      uart->istat.rxser_full = 0;
      uarts[i].istat.rxser_clks = 0;
      uart->istat.rxser_clks = 0;
    }
    }
  } else {
  } else {
    if (uarts[i].istat.rxser_full) {
    if (uart->istat.rxser_full) {
      if (uarts[i].char_clks <= uarts[i].istat.rxser_clks++) {
      if (uart->char_clks <= uart->istat.rxser_clks++) {
        /* Set unused character bits to zero and allow lsr register in fifo */
        /* Set unused character bits to zero and allow lsr register in fifo */
        uarts[i].iregs.rxser &= ((1 << ((uarts[i].regs.lcr & 3) + 5)) - 1) | 0xff00;
        uart->iregs.rxser &= ((1 << ((uart->regs.lcr & 3) + 5)) - 1) | 0xff00;
        debug(4, "Receiving 0x%02lx'%c' via UART%d...\n", uarts[i].iregs.rxser,
        debug(4, "Receiving 0x%02lx'%c' via UART (at %"PRIxADDR"...\n",
              (char)uarts[i].iregs.rxser, i);
              uart->iregs.rxser, (char)uart->iregs.rxser, uart->baseaddr);
        PRINTF ("%c", (char)uarts[i].iregs.rxser);
        PRINTF ("%c", (char)uart->iregs.rxser);
        uarts[i].istat.rxser_full = 0;
        uart->istat.rxser_full = 0;
        uarts[i].istat.rxser_clks = 0;
        uart->istat.rxser_clks = 0;
        uart_add_char (i, uarts[i].iregs.rxser);
        uart_add_char (uart, uart->iregs.rxser);
      }
      }
    }
    }
  }
  }
 
 
  /* Check if there is something waiting, and put it into rxser */
  /* Check if there is something waiting, and put it into rxser */
  if (uarts[i].regs.mcr & UART_MCR_LOOP) {
  if (uart->regs.mcr & UART_MCR_LOOP) {
    uarts[i].iregs.rxser = uarts[i].iregs.loopback;
    uart->iregs.rxser = uart->iregs.loopback;
    uarts[i].istat.rxser_full = 1;
    uart->istat.rxser_full = 1;
  } else {
  } else {
    if (!config.uarts[i].vapi_id) {
    if (!uart->vapi_id) {
      if(uarts[i].istat.rxser_full == 0) {
      if(uart->istat.rxser_full == 0) {
        if (uarts[i].slowdown)
        if (uart->slowdown)
          uarts[i].slowdown--;
          uart->slowdown--;
        else {
        else {
          char buffer[1];
          char buffer[1];
          retval = channel_read(channels[i], buffer, 1);
          retval = channel_read(uart->channel, buffer, 1);
          if(retval < 0)
          if(retval < 0)
                  perror(config.uarts[i].channel);
                  perror(uart->channel_str);
          else if(retval > 0) {
          else if(retval > 0) {
            uarts[i].iregs.rxser = (unsigned char)buffer[0];
            uart->iregs.rxser = (unsigned char)buffer[0];
            uarts[i].istat.rxser_full = 1;
            uart->istat.rxser_full = 1;
          } else
          } else
            uarts[i].slowdown = UART_FGETC_SLOWDOWN;
            uart->slowdown = UART_FGETC_SLOWDOWN;
        }
        }
      }
      }
    } else { /* VAPI */
    } else { /* VAPI */
      int received = 0;
      int received = 0;
      /* do not handle commands while receiving */
      /* do not handle commands while receiving */
      if (uarts[i].istat.rxser_full) return;
      if (uart->istat.rxser_full) return;
      while (!received) {
      while (!received) {
        if (uarts[i].vapi_buf_head_ptr != uarts[i].vapi_buf_tail_ptr) {
        if (uart->vapi_buf_head_ptr != uart->vapi_buf_tail_ptr) {
          unsigned long data = uarts[i].vapi_buf[uarts[i].vapi_buf_tail_ptr];
          unsigned long data = uart->vapi_buf[uart->vapi_buf_tail_ptr];
          debug(4, "Handling: %08lx (%i,%i)\n", data, uarts[i].vapi_buf_head_ptr, uarts[i].vapi_buf_tail_ptr);
          debug(4, "Handling: %08lx (%i,%i)\n", data, uart->vapi_buf_head_ptr,
          uarts[i].vapi_buf_tail_ptr = (uarts[i].vapi_buf_tail_ptr + 1) % UART_VAPI_BUF_LEN;
                uart->vapi_buf_tail_ptr);
 
          uart->vapi_buf_tail_ptr = (uart->vapi_buf_tail_ptr + 1) % UART_VAPI_BUF_LEN;
          switch (data >> 24) {
          switch (data >> 24) {
            case 0x00:
            case 0x00:
              uarts[i].vapi.lcr = (data >> 8) & 0xff;
              uart->vapi.lcr = (data >> 8) & 0xff;
              /* Put data into rx fifo */
              /* Put data into rx fifo */
              uarts[i].iregs.rxser = data & 0xff;
              uart->iregs.rxser = data & 0xff;
              uarts[i].vapi.char_clks = char_clks (uarts[i].vapi.dll, uarts[i].vapi.dlh, uarts[i].vapi.lcr);
              uart->vapi.char_clks = char_clks (uart->vapi.dll, uart->vapi.dlh, uart->vapi.lcr);
              if ((uarts[i].vapi.lcr & ~UART_LCR_SBC) != (uarts[i].regs.lcr & ~UART_LCR_SBC)
              if ((uart->vapi.lcr & ~UART_LCR_SBC) != (uart->regs.lcr & ~UART_LCR_SBC)
               || uarts[i].vapi.char_clks != uarts[i].char_clks
               || uart->vapi.char_clks != uart->char_clks
               || uarts[i].vapi.skew < -MAX_SKEW || uarts[i].vapi.skew > MAX_SKEW) {
               || uart->vapi.skew < -MAX_SKEW || uart->vapi.skew > MAX_SKEW) {
                debug (3, "WARNING: unmatched VAPI (%02x) and uart (%02x) modes.\n",
                debug (3, "WARNING: unmatched VAPI (%02x) and uart (%02x) modes.\n",
                      uarts[i].vapi.lcr & ~UART_LCR_SBC, uarts[i].regs.lcr & ~UART_LCR_SBC);
                      uart->vapi.lcr & ~UART_LCR_SBC, uart->regs.lcr & ~UART_LCR_SBC);
                /* Set error bits */
                /* Set error bits */
                uarts[i].iregs.rxser |= (UART_LSR_FRAME | UART_LSR_RXERR) << 8;
                uart->iregs.rxser |= (UART_LSR_FRAME | UART_LSR_RXERR) << 8;
                if (uarts[i].regs.lcr & UART_LCR_PARITY) uarts[i].iregs.rxser |= UART_LSR_PARITY << 8;
                if (uart->regs.lcr & UART_LCR_PARITY) uart->iregs.rxser |= UART_LSR_PARITY << 8;
              }
              }
              uarts[i].istat.rxser_full = 1;
              uart->istat.rxser_full = 1;
              received = 1;
              received = 1;
              break;
              break;
            case 0x01:
            case 0x01:
              uarts[i].vapi.dll = (data >> 0) & 0xff;
              uart->vapi.dll = (data >> 0) & 0xff;
              uarts[i].vapi.dlh = (data >> 8) & 0xff;
              uart->vapi.dlh = (data >> 8) & 0xff;
              break;
              break;
            case 0x02:
            case 0x02:
              uarts[i].vapi.lcr = (data >> 8) & 0xff;
              uart->vapi.lcr = (data >> 8) & 0xff;
              break;
              break;
            case 0x03:
            case 0x03:
              uarts[i].vapi.skew = (signed short)(data & 0xffff);
              uart->vapi.skew = (signed short)(data & 0xffff);
              break;
              break;
            case 0x04:
            case 0x04:
              uarts[i].vapi.next_break_cnt = data & 0xffff;
              uart->vapi.next_break_cnt = data & 0xffff;
              uarts[i].vapi.next_break = (data >> 16) & 1;
              uart->vapi.next_break = (data >> 16) & 1;
              break;
              break;
            default:
            default:
              debug (0, "WARNING: Invalid vapi command %02lx\n", data >> 24);
              debug (0, "WARNING: Invalid vapi command %02lx\n", data >> 24);
              break;
              break;
          }
          }
Line 512... Line 499...
      }
      }
    }
    }
  }
  }
 
 
  /***************** Loopback *****************/
  /***************** Loopback *****************/
  if (uarts[i].regs.mcr & UART_MCR_LOOP) {
  if (uart->regs.mcr & UART_MCR_LOOP) {
    debug(5, "uart_clock: Loopback\n");
    debug(5, "uart_clock: Loopback\n");
    if ((uarts[i].regs.mcr & UART_MCR_AUX2) !=
    if ((uart->regs.mcr & UART_MCR_AUX2) !=
        ((uarts[i].regs.msr & UART_MSR_DCD) >> 4))
        ((uart->regs.msr & UART_MSR_DCD) >> 4))
      uarts[i].regs.msr |= UART_MSR_DDCD;
      uart->regs.msr |= UART_MSR_DDCD;
    if ((uarts[i].regs.mcr & UART_MCR_AUX1) <
    if ((uart->regs.mcr & UART_MCR_AUX1) <
        ((uarts[i].regs.msr & UART_MSR_RI) >> 4))
        ((uart->regs.msr & UART_MSR_RI) >> 4))
      uarts[i].regs.msr |= UART_MSR_TERI;
      uart->regs.msr |= UART_MSR_TERI;
    if ((uarts[i].regs.mcr & UART_MCR_RTS) !=
    if ((uart->regs.mcr & UART_MCR_RTS) !=
        ((uarts[i].regs.msr & UART_MSR_CTS) >> 3))
        ((uart->regs.msr & UART_MSR_CTS) >> 3))
      uarts[i].regs.msr |= UART_MSR_DCTS;
      uart->regs.msr |= UART_MSR_DCTS;
    if ((uarts[i].regs.mcr & UART_MCR_DTR) !=
    if ((uart->regs.mcr & UART_MCR_DTR) !=
        ((uarts[i].regs.msr & UART_MSR_DSR) >> 5))
        ((uart->regs.msr & UART_MSR_DSR) >> 5))
      uarts[i].regs.msr |= UART_MSR_DDSR;
      uart->regs.msr |= UART_MSR_DDSR;
    uarts[i].regs.msr &= ~(UART_MSR_DCD | UART_MSR_RI
    uart->regs.msr &= ~(UART_MSR_DCD | UART_MSR_RI
              | UART_MSR_DSR | UART_MSR_CTS);
              | UART_MSR_DSR | UART_MSR_CTS);
    uarts[i].regs.msr |= ((uarts[i].regs.mcr & UART_MCR_AUX2) << 4);
    uart->regs.msr |= ((uart->regs.mcr & UART_MCR_AUX2) << 4);
    uarts[i].regs.msr |= ((uarts[i].regs.mcr & UART_MCR_AUX1) << 4);
    uart->regs.msr |= ((uart->regs.mcr & UART_MCR_AUX1) << 4);
    uarts[i].regs.msr |= ((uarts[i].regs.mcr & UART_MCR_RTS) << 3);
    uart->regs.msr |= ((uart->regs.mcr & UART_MCR_RTS) << 3);
    uarts[i].regs.msr |= ((uarts[i].regs.mcr & UART_MCR_DTR) << 5);
    uart->regs.msr |= ((uart->regs.mcr & UART_MCR_DTR) << 5);
  }
  }
 
 
  if (uarts[i].regs.lsr & UART_LSR_RDRDY)
  if (uart->regs.lsr & UART_LSR_RDRDY)
    uarts[i].istat.timeout_count++;
    uart->istat.timeout_count++;
 
 
  /* Update LSR error bits from the ones from rx FIFO */
  /* Update LSR error bits from the ones from rx FIFO */
  if (uarts[i].istat.rxbuf_full) {
  if (uart->istat.rxbuf_full) {
    uarts[i].regs.lsr |= uarts[i].regs.rxbuf[uarts[i].istat.rxbuf_tail] >> 8;
    uart->regs.lsr |= uart->regs.rxbuf[uart->istat.rxbuf_tail] >> 8;
    /* we must delete the lsr status, so that we can clear it from lsr */
    /* we must delete the lsr status, so that we can clear it from lsr */
    uarts[i].regs.rxbuf[uarts[i].istat.rxbuf_tail] &= 0xff;
    uart->regs.rxbuf[uart->istat.rxbuf_tail] &= 0xff;
  }
  }
 
 
  /* Interrupt detection in proper priority order. */
  /* Interrupt detection in proper priority order. */
  uarts[i].regs.iir = UART_IIR_NO_INT;
  uart->regs.iir = UART_IIR_NO_INT;
  if (uarts[i].regs.ier & UART_IER_RLSI &&                    /* Receiver LS */
  if (uart->regs.ier & UART_IER_RLSI &&                    /* Receiver LS */
      uarts[i].regs.lsr & (UART_LSR_OVRRUN | UART_LSR_PARITY
      uart->regs.lsr & (UART_LSR_OVRRUN | UART_LSR_PARITY
        | UART_LSR_FRAME | UART_LSR_BREAK)) {
        | UART_LSR_FRAME | UART_LSR_BREAK)) {
    uarts[i].regs.iir = UART_IIR_RLSI;
    uart->regs.iir = UART_IIR_RLSI;
  } else if ((uarts[i].regs.ier & UART_IER_RDI)               /* RD available */
  } else if ((uart->regs.ier & UART_IER_RDI)               /* RD available */
      && (uarts[i].istat.rxbuf_full >= UART_FIFO_TRIGGER(uarts[i].regs.fcr >> 6))
      && (uart->istat.rxbuf_full >= UART_FIFO_TRIGGER(uart->regs.fcr >> 6))
      && (uarts[i].regs.lsr & UART_LSR_RDRDY)) {
      && (uart->regs.lsr & UART_LSR_RDRDY)) {
    uarts[i].regs.iir = UART_IIR_RDI;
    uart->regs.iir = UART_IIR_RDI;
  } else if ((uarts[i].regs.ier & UART_IER_RDI)               /* timeout */
  } else if ((uart->regs.ier & UART_IER_RDI)               /* timeout */
      && (uarts[i].istat.timeout_count >= UART_CHAR_TIMEOUT * uarts[i].char_clks)
      && (uart->istat.timeout_count >= UART_CHAR_TIMEOUT * uart->char_clks)
      && (uarts[i].istat.rxbuf_head != uarts[i].istat.rxbuf_tail)) {
      && (uart->istat.rxbuf_head != uart->istat.rxbuf_tail)) {
    uarts[i].regs.iir = UART_IIR_CTI;
    uart->regs.iir = UART_IIR_CTI;
  } else if (uarts[i].regs.ier & UART_IER_THRI &&             /* Transm. empty */
  } else if (uart->regs.ier & UART_IER_THRI &&             /* Transm. empty */
      uarts[i].istat.thre_int == 1) {
      uart->istat.thre_int == 1) {
    uarts[i].regs.iir = UART_IIR_THRI;
    uart->regs.iir = UART_IIR_THRI;
  } else if (uarts[i].regs.ier & UART_IER_MSI &&              /* Modem status */
  } else if (uart->regs.ier & UART_IER_MSI &&              /* Modem status */
      uarts[i].regs.msr & (UART_MSR_DCTS | UART_MSR_DDSR
      uart->regs.msr & (UART_MSR_DCTS | UART_MSR_DDSR
        | UART_MSR_TERI | UART_MSR_DDCD)) {
        | UART_MSR_TERI | UART_MSR_DDCD)) {
    uarts[i].regs.iir = UART_IIR_MSI;
    uart->regs.iir = UART_IIR_MSI;
  }
  }
  if (!(uarts[i].regs.iir & UART_IIR_NO_INT)) {
  if (!(uart->regs.iir & UART_IIR_NO_INT)) {
    debug (4, "uarts[i].regs.iir = %i\t", uarts[i].regs.iir);
    debug (4, "uart->regs.iir = %i\t", uart->regs.iir);
    report_interrupt(config.uarts[i].irq);
    report_interrupt(uart->irq);
  }
  }
}
}
 
 
/* Reset.  It initializes all registers of all UART devices to zero values,
/* Reset.  It initializes all registers of all UART devices to zero values,
   (re)opens all RX/TX file streams and places devices in memory address
   (re)opens all RX/TX file streams and places devices in memory address
   space.  */
   space.  */
void uart_reset()
void uart_reset(void *dat)
{
{
  int i;
  struct dev_16450 *uart = dat;
  if (config.sim.verbose && config.nuarts) PRINTF("Resetting %u UART(s).\n", config.nuarts);
 
  memset(uarts, 0, sizeof(uarts));
 
 
 
  for(i = 0; i < config.nuarts; i++) {
  if (uart->channel_str && uart->channel_str[0]) { /* Try to create stream. */
    if (config.uarts[i].vapi_id) {
    if(uart->channel)
      if ((config.uarts[i].vapi_id & VAPI_DEVICE_ID) != i) {
      channel_close(uart->channel);
        fprintf (stderr, "ERROR: Wrong vapi_id (0x%lx) for uart %i, last byte is required to be %02x; ignoring.\n", config.uarts[i].vapi_id, i, i);
    else
        config.uarts[i].vapi_id = 0;
      uart->channel = channel_init(uart->channel_str);
      } else {
    if(channel_open(uart->channel) < 0) {
        vapi_install_handler (config.uarts[i].vapi_id, uart_vapi_read, NULL);
      debug (0, "WARNING: UART has problems with channel \"%s\".\n", uart->channel_str);
        register_memoryarea(config.uarts[i].baseaddr, UART_ADDR_SPACE, 1, 0, uart_read_byte, uart_write_byte, NULL);
    } else if (config.sim.verbose)
      }
      PRINTF("UART at 0x%"PRIxADDR" uses ", uart->baseaddr);
    } else if (config.uarts[i].channel[0]) { /* MM: Try to create stream.  */
 
      if(channels[i])
 
        channel_close(channels[i]);
 
      else
 
        channels[i] = channel_init(config.uarts[i].channel);
 
      if(channel_open(channels[i]) < 0) {
 
        debug (0, "WARNING: UART%d has problems with channel \"%s\".\n", i, config.uarts[i].channel);
 
        continue;
 
      }
 
      if (config.sim.verbose)
 
        PRINTF("UART%d at 0x%.8lx uses ", i, config.uarts[i].baseaddr);
 
      register_memoryarea(config.uarts[i].baseaddr, UART_ADDR_SPACE, 1, 0, uart_read_byte, uart_write_byte, NULL);
 
    } else {
    } else {
        debug (0, "WARNING: UART%d has no vapi nor channel specified\n", i);
    debug (0, "WARNING: UART at %"PRIxADDR" has no vapi nor channel specified\n", uart->baseaddr);
        continue;
 
    }
    }
 
 
    if (config.uarts[i].uart16550)
  if (uart->uart16550)
      uarts[i].fifo_len = 16;
    uart->fifo_len = 16;
    else
    else
      uarts[i].fifo_len = 1;
    uart->fifo_len = 1;
 
 
    uarts[i].istat.rxbuf_head = uarts[i].istat.rxbuf_tail = 0;
  uart->istat.rxbuf_head = uart->istat.rxbuf_tail = 0;
    uarts[i].istat.txbuf_head = uarts[i].istat.txbuf_tail = 0;
  uart->istat.txbuf_head = uart->istat.txbuf_tail = 0;
 
 
    uarts[i].istat.break_set = 0;
  uart->istat.txser_full = uart->istat.rxser_full = 0;
    uarts[i].istat.timeout_count = 0;
  uart->istat.txbuf_full = uart->istat.rxbuf_full = 0;
 
 
 
  uart->istat.txser_clks = uart->istat.rxser_clks = 0;
 
 
 
  uart->istat.thre_int = 0;
 
  uart->istat.break_set = 0;
 
  uart->istat.timeout_count = 0;
 
 
    // For FIFO-mode only, THRE interrupt is set when both THR and FIFO are empty
    // For FIFO-mode only, THRE interrupt is set when both THR and FIFO are empty
    uarts[i].istat.thre_int = (uarts[i].fifo_len == 16);
  uart->istat.thre_int = (uart->fifo_len == 16);
 
 
    uarts[i].slowdown = UART_FGETC_SLOWDOWN;
  uart->char_clks = 0;
 
  uart->slowdown = UART_FGETC_SLOWDOWN;
 
 
    uarts[i].regs.lcr = UART_LCR_RESET;
  uart->iregs.txser = 0;
    uarts[i].vapi.cur_break = uarts[i].vapi.cur_break_cnt = uarts[i].vapi.next_break = 0;
  uart->iregs.rxser = 0;
    uarts[i].vapi.next_break_cnt = -1;
  uart->iregs.loopback = 0;
    PRINTF ("%i\n", i);
 
    SCHED_ADD (uart_clock16, i, runtime.sim.cycles + UART_CLOCK_DIVIDER);
  memset(uart->regs.txbuf, 0, sizeof(uart->regs.txbuf));
  }
  memset(uart->regs.rxbuf, 0, sizeof(uart->regs.rxbuf));
 
 
 
  uart->regs.lcr = UART_LCR_RESET;
 
  uart->regs.dll = 0;
 
  uart->regs.dlh = 0;
 
  uart->regs.ier = 0;
 
  uart->regs.iir = 0;
 
  uart->regs.fcr = 0;
 
  uart->regs.lcr = UART_LCR_RESET;
 
  uart->regs.mcr = 0;
 
  uart->regs.lsr = 0;
 
  uart->regs.msr = 0;
 
  uart->regs.scr = 0;
 
 
 
  uart->vapi.cur_break = uart->vapi.cur_break_cnt = uart->vapi.next_break = 0;
 
  uart->vapi.next_break_cnt = -1;
 
  uart->vapi.break_sent = 0;
 
  uart->vapi.skew = 0;
 
  uart->vapi.lcr = 0;
 
  uart->vapi.dll = 0;
 
  uart->vapi.char_clks = 0;
 
 
 
  uart->vapi_buf_head_ptr = 0;
 
  uart->vapi_buf_tail_ptr = 0;
 
  memset(uart->vapi_buf, 0, sizeof(uart->vapi_buf));
 
 
 
  SCHED_ADD (uart_clock16, dat, runtime.sim.cycles + UART_CLOCK_DIVIDER);
}
}
 
 
/* Print register values on stdout. */
/* Print register values on stdout. */
void uart_status()
void uart_status(void *dat)
{
{
  int i, j;
  struct dev_16450 *uart = dat;
 
  int i;
 
 
  for(i = 0; i < config.nuarts; i++) {
  PRINTF("\nUART visible registers at 0x%"PRIxADDR":\n", uart->baseaddr);
    if ( !config.uarts[i].baseaddr )
 
      continue;
 
    PRINTF("\nUART%d visible registers at 0x%.8lx:\n", i,
 
           config.uarts[i].baseaddr);
 
    PRINTF("RXBUF: ");
    PRINTF("RXBUF: ");
    for (j = uarts[i].istat.rxbuf_head; j != uarts[i].istat.rxbuf_tail; j = (j + 1) % uarts[i].fifo_len)
  for (i = uart->istat.rxbuf_head; i != uart->istat.rxbuf_tail; i = (i + 1) % uart->fifo_len)
      PRINTF (" %.2x", uarts[i].regs.rxbuf[j]);
    PRINTF (" %.2x", uart->regs.rxbuf[i]);
    PRINTF("TXBUF: ");
    PRINTF("TXBUF: ");
    for (j = uarts[i].istat.txbuf_head; j != uarts[i].istat.txbuf_tail; j = (j + 1) % uarts[i].fifo_len)
  for (i = uart->istat.txbuf_head; i != uart->istat.txbuf_tail; i = (i + 1) % uart->fifo_len)
      PRINTF (" %.2x", uarts[i].regs.txbuf[j]);
    PRINTF (" %.2x", uart->regs.txbuf[i]);
    PRINTF("\n");
    PRINTF("\n");
    PRINTF("DLL  : %.2x  DLH  : %.2x\n", uarts[i].regs.dll, uarts[i].regs.dlh);
  PRINTF("DLL  : %.2x  DLH  : %.2x\n", uart->regs.dll, uart->regs.dlh);
    PRINTF("IER  : %.2x  IIR  : %.2x\n", uarts[i].regs.ier, uarts[i].regs.iir);
  PRINTF("IER  : %.2x  IIR  : %.2x\n", uart->regs.ier, uart->regs.iir);
    PRINTF("LCR  : %.2x  MCR  : %.2x\n", uarts[i].regs.lcr, uarts[i].regs.mcr);
  PRINTF("LCR  : %.2x  MCR  : %.2x\n", uart->regs.lcr, uart->regs.mcr);
    PRINTF("LSR  : %.2x  MSR  : %.2x\n", uarts[i].regs.lsr, uarts[i].regs.msr);
  PRINTF("LSR  : %.2x  MSR  : %.2x\n", uart->regs.lsr, uart->regs.msr);
    PRINTF("SCR  : %.2x\n", uarts[i].regs.scr);
  PRINTF("SCR  : %.2x\n", uart->regs.scr);
 
 
    PRINTF("\nInternal registers (sim debug):\n");
    PRINTF("\nInternal registers (sim debug):\n");
    PRINTF("RXSER: %.2lx  TXSER: %.2lx\n", uarts[i].iregs.rxser,
  PRINTF("RXSER: %.2lx  TXSER: %.2lx\n", uart->iregs.rxser, uart->iregs.txser);
           uarts[i].iregs.txser);
 
 
 
    PRINTF("\nInternal status (sim debug):\n");
    PRINTF("\nInternal status (sim debug):\n");
    PRINTF("char_clks: %ld\n", uarts[i].char_clks);
  PRINTF("char_clks: %ld\n", uart->char_clks);
    PRINTF("rxser_clks: %ld  txser_clks: %ld\n", uarts[i].istat.rxser_clks,
  PRINTF("rxser_clks: %ld  txser_clks: %ld\n", uart->istat.rxser_clks,
           uarts[i].istat.txser_clks);
         uart->istat.txser_clks);
    PRINTF("rxser: %d  txser: %d\n", uarts[i].istat.rxser_full, uarts[i].istat.txser_full);
  PRINTF("rxser: %d  txser: %d\n", uart->istat.rxser_full, uart->istat.txser_full);
    PRINTF("rxbuf_full: %d  txbuf_full: %d\n", uarts[i].istat.rxbuf_full, uarts[i].istat.txbuf_full);
  PRINTF("rxbuf_full: %d  txbuf_full: %d\n", uart->istat.rxbuf_full, uart->istat.txbuf_full);
    PRINTF("Using IRQ%i\n", config.uarts[i].irq);
  PRINTF("Using IRQ%i\n", uart->irq);
    if (config.uarts[i].vapi_id)
  if (uart->vapi_id)
      PRINTF ("Connected to vapi ID=%lx\n\n", config.uarts[i].vapi_id);
    PRINTF ("Connected to vapi ID=%lx\n\n", uart->vapi_id);
    /* TODO: replace by a channel_status
    /* TODO: replace by a channel_status
    else
    else
      PRINTF("RX fs: %p  TX fs: %p\n\n", uarts[i].rxfs, uarts[i].txfs);
    PRINTF("RX fs: %p  TX fs: %p\n\n", uart->rxfs, uart->txfs);
    */
    */
  }
  }
}
 
 
 
/*---------------------------------------------------[ UART configuration ]---*/
/*---------------------------------------------------[ UART configuration ]---*/
void uart_nuarts(union param_val val, void *dat)
 
{
 
  if (val.int_val >= 0 && val.int_val < MAX_UARTS)
 
    config.nuarts = val.int_val;
 
  else
 
    CONFIG_ERROR("invalid number of devices.");
 
}
 
 
 
void uart_baseaddr(union param_val val, void *dat)
void uart_baseaddr(union param_val val, void *dat)
{
{
  if (current_device >= 0 && current_device < config.nuarts)
  struct dev_16450 *uart = dat;
    config.uarts[current_device].baseaddr = val.addr_val;
  uart->baseaddr = val.addr_val;
  else
 
    CONFIG_ERROR("invalid device number.");
 
}
}
 
 
void uart_jitter(union param_val val, void *dat)
void uart_jitter(union param_val val, void *dat)
{
{
  if (current_device >= 0 && current_device < config.nuarts)
  struct dev_16450 *uart = dat;
    config.uarts[current_device].jitter = val.int_val;
  uart->jitter = val.int_val;
  else
 
    CONFIG_ERROR("invalid device number.");
 
}
}
 
 
void uart_irq(union param_val val, void *dat)
void uart_irq(union param_val val, void *dat)
{
{
  if (current_device >= 0 && current_device < config.nuarts)
  struct dev_16450 *uart = dat;
    config.uarts[current_device].irq = val.int_val;
  uart->irq = val.int_val;
  else
 
    CONFIG_ERROR("invalid device number.");
 
}
}
 
 
void uart_16550(union param_val val, void *dat)
void uart_16550(union param_val val, void *dat)
{
{
  if (current_device >= 0 && current_device < config.nuarts)
  struct dev_16450 *uart = dat;
    config.uarts[current_device].uart16550 = val.int_val;
  uart->uart16550 = val.int_val;
  else
 
    CONFIG_ERROR("invalid device number.");
 
}
}
 
 
void uart_channel(union param_val val, void *dat)
void uart_channel(union param_val val, void *dat)
{
{
  if (current_device >= 0 && current_device < config.nuarts)
  struct dev_16450 *uart = dat;
    strcpy (config.uarts[current_device].channel, val.str_val);
  if(!(uart->channel_str = strdup(val.str_val))) {
  else
    fprintf(stderr, "Peripheral 16450: Run out of memory\n");
    CONFIG_ERROR("invalid device number.");
    exit(-1);
 
  }
}
}
 
 
void uart_newway(union param_val val, void *dat)
void uart_newway(union param_val val, void *dat)
{
{
  CONFIG_ERROR(" txfile and rxfile and now obsolete.\n\tUse 'channel = \"file:rxfile,txfile\"' instead.");
  CONFIG_ERROR(" txfile and rxfile and now obsolete.\n\tUse 'channel = \"file:rxfile,txfile\"' instead.");
  exit(1);
  exit(1);
}
}
 
 
void uart_vapi_id(union param_val val, void *dat)
void uart_vapi_id(union param_val val, void *dat)
{
{
  if (current_device >= 0 && current_device < config.nuarts)
  struct dev_16450 *uart = dat;
    config.uarts[current_device].vapi_id = val.int_val;
  uart->vapi_id = val.int_val;
  else
}
    CONFIG_ERROR("invalid device number.");
 
 
void *uart_sec_start(void)
 
{
 
  struct dev_16450 *new = malloc(sizeof(struct dev_16450));
 
 
 
  if(!new) {
 
    fprintf(stderr, "Peripheral 16450: Run out of memory\n");
 
    exit(-1);
 
  }
 
 
 
  new->channel_str = NULL;
 
  new->channel = NULL;
 
  new->vapi_id = 0;
 
 
 
  return new;
 
}
 
 
 
void uart_sec_end(void *dat)
 
{
 
  struct dev_16450 *uart = dat;
 
 
 
  if(uart->vapi_id)
 
    vapi_install_handler(uart->vapi_id, uart_vapi_read, dat);
 
  register_memoryarea(uart->baseaddr, UART_ADDR_SPACE, 1, 0, uart_read_byte,
 
                      uart_write_byte, dat);
 
  reg_sim_reset(uart_reset, dat);
 
  reg_sim_stat(uart_status, dat);
}
}
 
 
void reg_uart_sec(void)
void reg_uart_sec(void)
{
{
  struct config_section *sec = reg_config_sec("uart", NULL, NULL);
  struct config_section *sec = reg_config_sec("uart", uart_sec_start,
 
                                              uart_sec_end);
 
 
  reg_config_param(sec, "nuarts", paramt_int, uart_nuarts);
 
  reg_config_param(sec, "device", paramt_int, change_device);
 
  reg_config_param(sec, "enddevice", paramt_none, end_device);
 
  reg_config_param(sec, "baseaddr", paramt_addr, uart_baseaddr);
  reg_config_param(sec, "baseaddr", paramt_addr, uart_baseaddr);
  reg_config_param(sec, "irq", paramt_int, uart_irq);
  reg_config_param(sec, "irq", paramt_int, uart_irq);
  reg_config_param(sec, "16550", paramt_int, uart_16550);
  reg_config_param(sec, "16550", paramt_int, uart_16550);
  reg_config_param(sec, "jitter", paramt_int, uart_jitter);
  reg_config_param(sec, "jitter", paramt_int, uart_jitter);
  reg_config_param(sec, "channel", paramt_str, uart_channel);
  reg_config_param(sec, "channel", paramt_str, uart_channel);

powered by: WebSVN 2.1.0

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