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

Subversion Repositories or1k

[/] [or1k/] [branches/] [stable_0_2_x/] [or1ksim/] [peripheral/] [16450.c] - Diff between revs 1504 and 1505

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

Rev 1504 Rev 1505
Line 556... Line 556...
{
{
  if(!uart->vapi_id)
  if(!uart->vapi_id)
    SCHED_ADD(uart_check_char, uart, UART_FGETC_SLOWDOWN * UART_CLOCK_DIVIDER);
    SCHED_ADD(uart_check_char, uart, UART_FGETC_SLOWDOWN * UART_CLOCK_DIVIDER);
}
}
 
 
 
/*----------------------------------------------------[ UART I/O handling ]---*/
/* Set a specific UART register with value. */
/* Set a specific UART register with value. */
void uart_write_byte(oraddr_t addr, uint8_t value, void *dat)
void uart_write_byte(oraddr_t addr, uint8_t value, void *dat)
{
{
  struct dev_16450 *uart = dat;
  struct dev_16450 *uart = dat;
 
 
  TRACE("uart_write_byte(%"PRIxADDR",%02"PRIx8")\n", addr, value);
 
 
 
  if (uart->regs.lcr & UART_LCR_DLAB) {
  if (uart->regs.lcr & UART_LCR_DLAB) {
    switch (addr) {
    switch (addr) {
      case UART_DLL:
      case UART_DLL:
        uart->regs.dll = value;
        uart->regs.dll = value;
        uart->char_clks = char_clks(uart->regs.dll, uart->regs.dlh, uart->regs.lcr);
        uart->char_clks = char_clks(uart->regs.dll, uart->regs.dlh, uart->regs.lcr);
        TRACE("\tSetting char_clks to %li (%02x, %02x, %02x)\n", uart->char_clks,
        TRACE("\tSetting char_clks to %li (%02x, %02x, %02x)\n", uart->char_clks,
              uart->regs.dll, uart->regs.dlh, uart->regs.lcr);
              uart->regs.dll, uart->regs.dlh, uart->regs.lcr);
        return;
        return;
      case UART_DLH:
      case UART_DLH:
 
        TRACE("Setting dlh with %"PRIx8"\n", value);
        uart->regs.dlh = value;
        uart->regs.dlh = value;
        return;
        return;
    }
    }
  }
  }
 
 
  switch (addr) {
  switch (addr) {
    case UART_TXBUF:
    case UART_TXBUF:
 
      TRACE("Adding %"PRIx8" to TX FIFO\n", value);
      uart->regs.lsr &= ~UART_LSR_TXBUFE;
      uart->regs.lsr &= ~UART_LSR_TXBUFE;
      if (uart->istat.txbuf_full < uart->fifo_len) {
      if (uart->istat.txbuf_full < uart->fifo_len) {
        uart->regs.txbuf[uart->istat.txbuf_head] = value;
        uart->regs.txbuf[uart->istat.txbuf_head] = value;
        uart->istat.txbuf_head = (uart->istat.txbuf_head + 1) % uart->fifo_len;
        uart->istat.txbuf_head = (uart->istat.txbuf_head + 1) % uart->fifo_len;
        if(!uart->istat.txbuf_full++ && (uart->regs.lsr & UART_LSR_TXSERE))
        if(!uart->istat.txbuf_full++ && (uart->regs.lsr & UART_LSR_TXSERE))
Line 591... Line 592...
        uart->regs.txbuf[uart->istat.txbuf_head] = value;
        uart->regs.txbuf[uart->istat.txbuf_head] = value;
 
 
      uart_clear_int(uart, UART_IIR_THRI);
      uart_clear_int(uart, UART_IIR_THRI);
      break;
      break;
    case UART_FCR:
    case UART_FCR:
 
      TRACE("Setting FCR reg with %"PRIx8"\n", value);
      uart->regs.fcr = value & UART_VALID_FCR;
      uart->regs.fcr = value & UART_VALID_FCR;
      if ((uart->fifo_len == 1 && (value & UART_FCR_FIE))
      if ((uart->fifo_len == 1 && (value & UART_FCR_FIE))
       || (uart->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;
      uart->fifo_len = (value & UART_FCR_FIE) ? 16 : 1;
      uart->fifo_len = (value & UART_FCR_FIE) ? 16 : 1;
Line 618... Line 620...
        uart_clear_int(uart, UART_IIR_CTI);
        uart_clear_int(uart, UART_IIR_CTI);
      }
      }
      break;
      break;
    case UART_IER:
    case UART_IER:
      uart->regs.ier = value & UART_VALID_IER;
      uart->regs.ier = value & UART_VALID_IER;
 
      TRACE("Enabling 0x%02x interrupts with 0x%x interrupts pending\n",
 
            value, uart->istat.ints);
      SCHED_ADD(uart_next_int, uart, 0);
      SCHED_ADD(uart_next_int, uart, 0);
      break;
      break;
    case UART_LCR:
    case UART_LCR:
 
      TRACE("Setting LCR reg with %"PRIx8"\n", value);
      if((uart->regs.lcr & UART_LCR_SBC) != (value & UART_LCR_SBC)) {
      if((uart->regs.lcr & UART_LCR_SBC) != (value & UART_LCR_SBC)) {
        if((value & UART_LCR_SBC) && !(uart->regs.lsr & UART_LSR_TXSERE)) {
        if((value & UART_LCR_SBC) && !(uart->regs.lsr & UART_LSR_TXSERE)) {
          /* Schedule a job to send the break char */
          /* Schedule a job to send the break char */
          SCHED_FIND_REMOVE(uart_char_clock, uart);
          SCHED_FIND_REMOVE(uart_char_clock, uart);
          SCHED_ADD(uart_send_break, uart, 0);
          SCHED_ADD(uart_send_break, uart, 0);
Line 638... Line 643...
      }
      }
      uart->regs.lcr = value & UART_VALID_LCR;
      uart->regs.lcr = value & UART_VALID_LCR;
      uart->char_clks = char_clks(uart->regs.dll, uart->regs.dlh, uart->regs.lcr);
      uart->char_clks = char_clks(uart->regs.dll, uart->regs.dlh, uart->regs.lcr);
      break;
      break;
    case UART_MCR:
    case UART_MCR:
 
      TRACE("Setting MCR reg with %"PRIx8"\n", value);
      uart->regs.mcr = value & UART_VALID_MCR;
      uart->regs.mcr = value & UART_VALID_MCR;
      uart_loopback(uart);
      uart_loopback(uart);
      break;
      break;
    case UART_SCR:
    case UART_SCR:
 
      TRACE("Setting SCR reg with %"PRIx8"\n", value);
      uart->regs.scr = value;
      uart->regs.scr = value;
      break;
      break;
    default:
    default:
      TRACE("write out of range (addr %x)\n", addr);
      TRACE("write out of range (addr %"PRIxADDR")\n", addr);
  }
  }
}
}
 
 
/* Read a specific UART register. */
/* Read a specific UART register. */
uint8_t uart_read_byte(oraddr_t addr, void *dat)
uint8_t uart_read_byte(oraddr_t addr, void *dat)
{
{
  struct dev_16450 *uart = dat;
  struct dev_16450 *uart = dat;
  uint8_t value = 0;
  uint8_t value = 0;
 
 
  TRACE("uart_read_byte(%"PRIxADDR")", addr);
 
 
 
  if (uart->regs.lcr & UART_LCR_DLAB) {
  if (uart->regs.lcr & UART_LCR_DLAB) {
    switch (addr) {
    switch (addr) {
      case UART_DLL:
      case UART_DLL:
        value = uart->regs.dll;
        value = uart->regs.dll;
        TRACE("= %"PRIx8"\n", value);
        TRACE("reading DLL = %"PRIx8"\n", value);
        return value;
        return value;
      case UART_DLH:
      case UART_DLH:
        value = uart->regs.dlh;
        value = uart->regs.dlh;
        TRACE("= %"PRIx8"\n", value);
        TRACE("reading DLH = %"PRIx8"\n", value);
        return value;
        return value;
    }
    }
  }
  }
 
 
  switch (addr) {
  switch (addr) {
Line 677... Line 682...
      { /* Print out FIFO for debugging */
      { /* Print out FIFO for debugging */
        int i;
        int i;
        TRACE("(%i/%i, %i, %i:", uart->istat.rxbuf_full, uart->fifo_len,
        TRACE("(%i/%i, %i, %i:", uart->istat.rxbuf_full, uart->fifo_len,
              uart->istat.rxbuf_head, uart->istat.rxbuf_tail);
              uart->istat.rxbuf_head, uart->istat.rxbuf_tail);
        for (i = 0; i < uart->istat.rxbuf_full; i++)
        for (i = 0; i < uart->istat.rxbuf_full; i++)
          TRACE("%02x ", uart->regs.rxbuf[(uart->istat.rxbuf_tail + i) % uart->fifo_len]);
          TRACE("%02x ",
 
                uart->regs.rxbuf[(uart->istat.rxbuf_tail + i) % uart->fifo_len]);
        TRACE(")");
        TRACE(")");
      }
      }
      if (uart->istat.rxbuf_full) {
      if (uart->istat.rxbuf_full) {
        value = uart->regs.rxbuf[uart->istat.rxbuf_tail];
        value = uart->regs.rxbuf[uart->istat.rxbuf_tail];
        uart->istat.rxbuf_tail = (uart->istat.rxbuf_tail + 1) % uart->fifo_len;
        uart->istat.rxbuf_tail = (uart->istat.rxbuf_tail + 1) % uart->fifo_len;
Line 707... Line 713...
        uart->regs.lsr &= ~UART_LSR_RDRDY;
        uart->regs.lsr &= ~UART_LSR_RDRDY;
      }
      }
      break;
      break;
    case UART_IER:
    case UART_IER:
      value = uart->regs.ier & UART_VALID_IER;
      value = uart->regs.ier & UART_VALID_IER;
 
      TRACE("reading IER = %"PRIx8"\n", value);
      break;
      break;
    case UART_IIR:
    case UART_IIR:
      value = (uart->regs.iir & UART_VALID_IIR) | 0xc0;
      value = (uart->regs.iir & UART_VALID_IIR) | 0xc0;
      /* Only clear the thri interrupt if it is the one we are repporting */
      /* Only clear the thri interrupt if it is the one we are repporting */
      if(uart->regs.iir == UART_IIR_THRI)
      if(uart->regs.iir == UART_IIR_THRI)
        uart_clear_int(uart, UART_IIR_THRI);
        uart_clear_int(uart, UART_IIR_THRI);
 
      TRACE("reading IIR = %"PRIx8"\n", value);
      break;
      break;
    case UART_LCR:
    case UART_LCR:
      value = uart->regs.lcr & UART_VALID_LCR;
      value = uart->regs.lcr & UART_VALID_LCR;
 
      TRACE("reading LCR = %"PRIx8"\n", value);
      break;
      break;
    case UART_MCR:
    case UART_MCR:
      value = 0;
      value = 0;
 
      TRACE("reading MCR = %"PRIx8"\n", value);
      break;
      break;
    case UART_LSR:
    case UART_LSR:
      value = uart->regs.lsr & UART_VALID_LSR;
      value = uart->regs.lsr & UART_VALID_LSR;
      uart->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);
      /* Clear potentially pending RLSI interrupt */
      /* Clear potentially pending RLSI interrupt */
      uart_clear_int(uart, UART_IIR_RLSI);
      uart_clear_int(uart, UART_IIR_RLSI);
 
      TRACE("reading LSR = %"PRIx8"\n", value);
      break;
      break;
    case UART_MSR:
    case UART_MSR:
      value = uart->regs.msr & UART_VALID_MSR;
      value = uart->regs.msr & UART_VALID_MSR;
      uart->regs.msr = 0;
      uart->regs.msr = 0;
      uart_clear_int(uart, UART_IIR_MSI);
      uart_clear_int(uart, UART_IIR_MSI);
      uart_loopback(uart);
      uart_loopback(uart);
 
      TRACE("reading MSR = %"PRIx8"\n", value);
      break;
      break;
    case UART_SCR:
    case UART_SCR:
      value = uart->regs.scr;
      value = uart->regs.scr;
 
      TRACE("reading SCR = %"PRIx8"\n", value);
      break;
      break;
    default:
    default:
      TRACE("read out of range (addr %"PRIxADDR")\n", addr);
      TRACE("read out of range (addr %"PRIxADDR")\n", addr);
  }
  }
  TRACE(" = %"PRIx8"\n", value);
 
  return value;
  return value;
}
}
 
 
/*--------------------------------------------------------[ VAPI handling ]---*/
/*--------------------------------------------------------[ VAPI handling ]---*/
/* Decodes the read vapi command */
/* Decodes the read vapi command */
Line 844... Line 856...
  }
  }
  if(!uart->istat.receiveing)
  if(!uart->istat.receiveing)
    uart_vapi_cmd(uart);
    uart_vapi_cmd(uart);
}
}
 
 
 
/*--------------------------------------------------------[ Sim callbacks ]---*/
/* 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 *dat)
void uart_reset(void *dat)
{
{
  struct dev_16450 *uart = dat;
  struct dev_16450 *uart = dat;
 
 
  if(uart->vapi_id) {
  if(uart->vapi_id) {

powered by: WebSVN 2.1.0

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