Exemplo n.º 1
0
/*
 * Transmit-data-empty ISR
 *
 * The same routine for all interrupt sources of the same type.
 */
static rtems_isr sh_sci_tx_isr(rtems_vector_number vector)
{
    int minor;

    for (minor = 0; minor < Console_Port_Count; minor++) {
        if (Console_Port_Tbl[minor]->ulDataPort == vector) {
            /*
             * FIXME: Error handling should be added
             */

            /*
             * Mask end-of-transmission interrupt
             */
            SH_SCI_REG_MASK(SCI_TIE, minor, SCI_SCR);

            if (rtems_termios_dequeue_characters(
                   Console_Port_Data[minor].termios_data, 1)) {
                /*
                 * More characters to be received - interrupt must be enabled
                 */
                SH_SCI_REG_FLAG(SCI_TIE, minor, SCI_SCR);
            }
            break;
        }
    }
}
Exemplo n.º 2
0
void
BSP_uart_termios_isr_com2()
{
  unsigned char buf[40];
  int      off, ret, vect;

  off = 0;

  for(;;)
    {
      vect = uread(BSP_UART_COM2, IIR) & 0xf;

      switch(vect)
	{
	case NO_MORE_INTR :
	  /* No more interrupts */
	  if(off != 0)
	    {
	      /* Update rx buffer */
	      rtems_termios_enqueue_raw_characters(termios_ttyp_com2,
						   (char *)buf,
						   off);
	    }
	  return;
	case TRANSMITTER_HODING_REGISTER_EMPTY :
	  /*
	   * TX holding empty: we have to disable these interrupts
	   * if there is nothing more to send.
	   */

	  ret = rtems_termios_dequeue_characters(termios_ttyp_com2, 1);

	  /* If nothing else to send disable interrupts */
	  if(ret == 0)
	    {
	      uwrite(BSP_UART_COM2, IER,
		     (RECEIVE_ENABLE  |
		      RECEIVER_LINE_ST_ENABLE
		     )
		    );
              termios_tx_active_com2 = 0;
	    }
	  break;
	case RECEIVER_DATA_AVAIL :
	case CHARACTER_TIMEOUT_INDICATION:
	  /* RX data ready */
	  assert(off < sizeof(buf));
	  buf[off++] = uread(BSP_UART_COM2, RBR);
	  break;
	case RECEIVER_ERROR:
	  /* RX error: eat character */
	   uartError(BSP_UART_COM2);
	  break;
	default:
	  /* Should not happen */
	  assert(0);
	  return;
	}
    }
}
Exemplo n.º 3
0
/**
 * @brief sci interrupt handler
 *
 * Handler checks which interrupt occured and provides nessesary maintenance
 * dequeue characters in termios driver whether character is send succesfully
 * enqueue characters in termios driver whether character is recieved
 *
 * @param[in] arg rtems_termios_tty
 * @retval Void
 */
static void tms570_sci_interrupt_handler(void * arg)
{
  rtems_termios_tty *tty = arg;
  tms570_sci_context *ctx = rtems_termios_get_device_context(tty);
  char buf[TMS570_SCI_BUFFER_SIZE];
  size_t n;

  /*
   * Check if we have received something.
   */
   if ( (ctx->regs->FLR & TMS570_SCI_FLR_RXRDY ) == TMS570_SCI_FLR_RXRDY ) {
      n = tms570_sci_read_received_chars(ctx, buf, TMS570_SCI_BUFFER_SIZE);
      if ( n > 0 ) {
        /* Hand the data over to the Termios infrastructure */
        rtems_termios_enqueue_raw_characters(tty, buf, n);
      }
    }
  /*
   * Check if we have something transmitted.
   */
  if ( (ctx->regs->FLR & TMS570_SCI_FLR_TXRDY ) == TMS570_SCI_FLR_TXRDY ) {
    n = tms570_sci_transmitted_chars(ctx);
    if ( n > 0 ) {
      /*
       * Notify Termios that we have transmitted some characters.  It
       * will call now the interrupt write function if more characters
       * are ready for transmission.
       */
      rtems_termios_dequeue_characters(tty, n);
    }
  }
}
Exemplo n.º 4
0
/*
 * Interrupt handling.
 */
static void
m5xx_sci_interrupt_handler (rtems_irq_hdl_param unused)
{
  int minor;

  for ( minor = 0; minor < NUM_PORTS; minor++ ) {
    sci_desc *desc = &sci_descs[minor];
    int sccr1 = desc->regs->sccr1;
    int scsr = desc->regs->scsr;

    /*
     * Character received?
     */
    if ((sccr1 & QSMCM_SCI_RIE) && (scsr & QSMCM_SCI_RDRF)) {
      char c = desc->regs->scdr;
      rtems_termios_enqueue_raw_characters(desc->ttyp, &c, 1);
    }
    /*
     * Transmitter empty?
     */
    if ((sccr1 & QSMCM_SCI_TIE) && (scsr & QSMCM_SCI_TDRE)) {
      desc->regs->sccr1 &= ~QSMCM_SCI_TIE;
      rtems_termios_dequeue_characters (desc->ttyp, 1);
    }
  }
}
Exemplo n.º 5
0
/*
 * Interrupt handler
 */
static rtems_isr
smc1InterruptHandler (rtems_vector_number v)
{
  /*
   * Buffer received?
   */
  if (m360.smc1.smce & 0x1) {
    m360.smc1.smce = 0x1;
    while ((smcRxBd->status & M360_BD_EMPTY) == 0) {
      rtems_termios_enqueue_raw_characters (smc1ttyp,
              (char *)smcRxBd->buffer,
              smcRxBd->length);
      smcRxBd->status = M360_BD_EMPTY | M360_BD_WRAP | M360_BD_INTERRUPT;
    }
  }

  /*
   * Buffer transmitted?
   */
  if (m360.smc1.smce & 0x2) {
    m360.smc1.smce = 0x2;
    if ((smcTxBd->status & M360_BD_READY) == 0)
      rtems_termios_dequeue_characters (smc1ttyp, smcTxBd->length);
  }
  m360.cisr = 1UL << 4;  /* Clear SMC1 interrupt-in-service bit */
}
Exemplo n.º 6
0
/* sh4uart2_interrupt_transmit --
 *     UART interrupt handler routine -- SCI
 *     It continues transmit data when old part of data is transmitted
 *
 * PARAMETERS:
 *     vec - interrupt vector number
 *
 * RETURNS:
 *     none
 */
static rtems_isr
sh4uart2_interrupt_transmit(rtems_vector_number vec)
{
  volatile uint8_t *ssr1 = (volatile uint8_t *)SH7750_SCSSR1;
  volatile uint16_t *scr2 = (volatile uint16_t *)SH7750_SCSCR2;

  /* Find UART descriptor from vector number */
  sh4uart *uart = &sh4_uarts[1];

  if (uart->tx_buf != NULL && uart->tx_ptr < uart->tx_buf_len) {
    while ((SCSSR2 & SH7750_SCSSR2_TDFE) != 0) {
        int i;
        for (i = 0;
             i < 16 - TRANSMIT_TRIGGER_VALUE(SCFCR2 & SH7750_SCFCR2_TTRG);
             i++)
          SCTDR2 = uart->tx_buf[uart->tx_ptr++];
        while ((SCSSR1 & SH7750_SCSSR1_TDRE) == 0 ||
                (SCSSR1 & SH7750_SCSSR1_TEND) == 0);
        *ssr1 &= ~(SH7750_SCSSR1_TDRE | SH7750_SCSSR2_TEND);
    }
  } else {
    register int dequeue = uart->tx_buf_len;

    uart->tx_buf = NULL;
    uart->tx_ptr = uart->tx_buf_len = 0;

    /* Disable interrupts while we do not have any data to transmit */
    *scr2 &= ~SH7750_SCSCR_TIE;

    rtems_termios_dequeue_characters(uart->tty, dequeue);
  }
}
Exemplo n.º 7
0
/* sh4uart1_interrupt_transmit --
 *     UART interrupt handler routine -- SCI
 *     It continues transmit data when old part of data is transmitted
 *
 * PARAMETERS:
 *     vec - interrupt vector number
 *
 * RETURNS:
 *     none
 */
static rtems_isr
sh4uart1_interrupt_transmit(rtems_vector_number vec)
{
  volatile uint8_t *scr1 = (volatile uint8_t *)SH7750_SCSCR1;
  volatile uint8_t *ssr1 = (volatile uint8_t *)SH7750_SCSSR1;

  /* Find UART descriptor from vector number */
  sh4uart *uart = &sh4_uarts[0];

  if (uart->tx_buf != NULL && uart->tx_ptr < uart->tx_buf_len) {
    while ((SCSSR1 & SH7750_SCSSR1_TDRE) != 0 &&
            uart->tx_ptr < uart->tx_buf_len) {
        SCTDR1 = uart->tx_buf[uart->tx_ptr++];
        *ssr1 &= ~SH7750_SCSSR1_TDRE;
    }
  } else {
    register int dequeue = uart->tx_buf_len;

    uart->tx_buf = NULL;
    uart->tx_ptr = uart->tx_buf_len = 0;

    /* Disable interrupts while we do not have any data to transmit */
    *scr1 &= ~SH7750_SCSCR_TIE;

    rtems_termios_dequeue_characters(uart->tty, dequeue);
  }
}
Exemplo n.º 8
0
/* Handle UART interrupts */
static void apbuart_cons_isr(void *arg)
{
	rtems_termios_tty *tty = arg;
	rtems_termios_device_context *base;
	struct console_dev *condev = rtems_termios_get_device_context(tty);
	struct apbuart_priv *uart = condev_get_priv(condev);
	struct apbuart_regs *regs = uart->regs;
	unsigned int status;
	char buf[33];
	int cnt;

	if (uart->mode == TERMIOS_TASK_DRIVEN) {
		if ((status = regs->status) & APBUART_STATUS_DR) {
			rtems_interrupt_lock_context lock_context;

			/* Turn off RX interrupts */
			base = rtems_termios_get_device_context(tty);
			rtems_termios_device_lock_acquire(base, &lock_context);
			regs->ctrl &=
			    ~(APBUART_CTRL_DI | APBUART_CTRL_RI |
			      APBUART_CTRL_RF);
			rtems_termios_device_lock_release(base, &lock_context);
			/* Activate termios RX daemon task */
			rtems_termios_rxirq_occured(tty);
		}
	} else {
		/*
		 * Get all new characters from APBUART RX (FIFO) and store them
		 * on the stack. Then tell termios about the new characters.
		 * Maximum APBUART RX FIFO size is 32 characters.
		 */
		cnt = 0;
		while (
			((status=regs->status) & APBUART_STATUS_DR) &&
			(cnt < sizeof(buf))
		) {
			buf[cnt] = regs->data;
			cnt++;
		}
		if (0 < cnt) {
			/* Tell termios layer about new characters */
			rtems_termios_enqueue_raw_characters(tty, &buf[0], cnt);
		}
	}

	if (uart->sending && (status & APBUART_STATUS_TE)) {
		/* Tell close that we sent everything */
		cnt = uart->sending;

		/*
		 * Tell termios how much we have sent. dequeue() may call
		 * write_interrupt() to refill the transmitter.
		 * write_interrupt() will eventually be called with 0 len to
		 * disable TX interrupts.
		 */
		rtems_termios_dequeue_characters(tty, cnt);
	}
}
Exemplo n.º 9
0
rtems_timer_service_routine Tx_ISR(
  rtems_id  ignored_id,
  void     *ignored_address
)
{
  rtems_termios_dequeue_characters (Ttyp, 1);

  (void) rtems_timer_fire_after( Tx_Timer, 10, Tx_ISR, NULL );
}
Exemplo n.º 10
0
static rtems_isr mmconsole_interrupt(rtems_vector_number n)
{
  char c;
  while (MM_READ(MM_UART_STAT) & UART_STAT_RX_EVT) {
    c = MM_READ(MM_UART_RXTX);
    MM_WRITE(MM_UART_STAT, UART_STAT_RX_EVT);
    rtems_termios_enqueue_raw_characters(tty, &c, 1);
  }
  if (MM_READ(MM_UART_STAT) & UART_STAT_TX_EVT) {
    MM_WRITE(MM_UART_STAT, UART_STAT_TX_EVT);
    rtems_termios_dequeue_characters(tty, 1);
  }
  lm32_interrupt_ack(1 << MM_IRQ_UART);
}
Exemplo n.º 11
0
/**
 * @brief Process interrupt.
 */
NS16550_STATIC void ns16550_process( int minor)
{
  console_tbl *c = Console_Port_Tbl [minor];
  console_data *d = &Console_Port_Data [minor];
  ns16550_context *ctx = d->pDeviceContext;
  uint32_t port = c->ulCtrlPort1;
  getRegister_f get = c->getRegister;
  int i = 0;
  char buf [SP_FIFO_SIZE];

  /* Iterate until no more interrupts are pending */
  do {
    /* Fetch received characters */
    for (i = 0; i < SP_FIFO_SIZE; ++i) {
      if ((get( port, NS16550_LINE_STATUS) & SP_LSR_RDY) != 0) {
        buf [i] = (char) get(port, NS16550_RECEIVE_BUFFER);
      } else {
        break;
      }
    }

    /* Enqueue fetched characters */
    rtems_termios_enqueue_raw_characters( d->termios_data, buf, i);

    /* Check if we can dequeue transmitted characters */
    if (ctx->transmitFifoChars > 0
        && (get( port, NS16550_LINE_STATUS) & SP_LSR_THOLD) != 0) {
      unsigned chars = ctx->transmitFifoChars;

      /*
       * We finished the transmission, so clear the number of characters in the
       * transmit FIFO.
       */
      ctx->transmitFifoChars = 0;

      /* Dequeue transmitted characters */
      if (rtems_termios_dequeue_characters( d->termios_data, chars) == 0) {
        /* Nothing to do */
        d->bActive = false;
        ns16550_enable_interrupts( c, NS16550_ENABLE_ALL_INTR_EXCEPT_TX);
      }
    }
  } while ((get( port, NS16550_INTERRUPT_ID) & SP_IID_0) == 0);
}
Exemplo n.º 12
0
static void atsam_usart_interrupt(void *arg)
{
  rtems_termios_tty *tty = arg;
  atsam_usart_context *ctx = rtems_termios_get_device_context(tty);
  Usart *regs = ctx->regs;
  uint32_t csr = regs->US_CSR;

  while ((csr & US_CSR_RXRDY) != 0) {
    char c = (char) regs->US_RHR;

    rtems_termios_enqueue_raw_characters(tty, &c, 1);

    csr = regs->US_CSR;
  }

  if (ctx->transmitting && (csr & US_CSR_TXEMPTY) != 0) {
    rtems_termios_dequeue_characters(tty, 1);
  }
}
Exemplo n.º 13
0
static void imx_uart_tx_isr(rtems_irq_hdl_param param)
{
    imx_uart_data_t *uart_data = param;
    int len;
    int minor = uart_data->minor;


    if (uart_data->idx < uart_data->len) {
        while ( (uart_data->regs->sr1 & MC9328MXL_UART_SR1_TRDY) &&
                (uart_data->idx < uart_data->len)) {
            uart_data->regs->txd = uart_data->buf[uart_data->idx];
            uart_data->idx++;
        }
    } else {
        len = uart_data->len;
        uart_data->len = 0;
        imx_uart_data[minor].regs->cr1 &= ~MC9328MXL_UART_CR1_TXMPTYEN;
        rtems_termios_dequeue_characters(uart_data->tty, len);
    }
}
Exemplo n.º 14
0
static void pl050_interrupt(void *arg)
{
  int minor = (int) arg;
  const console_data *cd = &Console_Port_Data[minor];
  volatile pl050 *regs = pl050_get_regs(minor);
  uint32_t kmiir_rx = PL050_KMIIR_KMIRXINTR;
  uint32_t kmiir_tx = (regs->kmicr & PL050_KMICR_KMITXINTREN) != 0 ?
    PL050_KMIIR_KMITXINTR : 0;
  uint32_t kmiir = regs->kmiir;

  if ((kmiir & kmiir_rx) != 0) {
    char c = (char) PL050_KMIDATA_KMIDATA_GET(regs->kmidata);

    rtems_termios_enqueue_raw_characters(cd->termios_data, &c, 1);
  }

  if ((kmiir & kmiir_tx) != 0) {
    rtems_termios_dequeue_characters(cd->termios_data, 1);
  }
}
Exemplo n.º 15
0
Arquivo: hsu.c Projeto: Fyleo/rtems
static void lpc32xx_hsu_interrupt_handler(void *arg)
{
  int minor = (int) arg;
  console_tbl *ct = Console_Port_Tbl [minor];
  console_data *cd = &Console_Port_Data [minor];
  volatile lpc32xx_hsu *hsu = (volatile lpc32xx_hsu *) ct->ulCtrlPort1;

  /* Iterate until no more interrupts are pending */
  do {
    int chars_to_dequeue = (int) cd->pDeviceContext;
    int rv = 0;
    int i = 0;
    char buf [HSU_FIFO_SIZE];

    /* Enqueue received characters */
    while (i < HSU_FIFO_SIZE) {
      uint32_t in = hsu->fifo;

      if ((in & HSU_RX_EMPTY) == 0) {
        if ((in & HSU_RX_BREAK) == 0) {
          buf [i] = in & HSU_RX_DATA_MASK;
          ++i;
        }
      } else {
        break;
      }
    }
    rtems_termios_enqueue_raw_characters(cd->termios_data, buf, i);

    /* Dequeue transmitted characters */
    cd->pDeviceContext = 0;
    rv = rtems_termios_dequeue_characters(cd->termios_data, chars_to_dequeue);
    if (rv == 0) {
      /* Nothing to transmit */
      cd->bActive = false;
      hsu->ctrl = HSU_CTRL_RX_INTR_ENABLED;
      hsu->iir = HSU_IIR_TX;
    }
  } while ((hsu->iir & HSU_IIR_MASK) != 0);
}
Exemplo n.º 16
0
static void erc32_console_isr_b(
  rtems_vector_number vector
)
{
  console_data *cd = &Console_Port_Data[1];

  /* check for error */
  if (ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_ERRB) {
      ERC32_MEC.UART_Status = ERC32_MEC_UART_STATUS_CLRB;
      ERC32_MEC.Control = ERC32_MEC.Control;
  }

  do {
    int chars_to_dequeue = (int)cd->pDeviceContext;
    int rv = 0;
    int i = 0;
    char buf[CONSOLE_BUF_SIZE];
        
    /* enqueue received chars */
    while (i < CONSOLE_BUF_SIZE) {
      if (!(ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_DRB))
        break;
      buf[i] = ERC32_MEC.UART_Channel_B;
      ++i;
    }
    if ( i ) 
      rtems_termios_enqueue_raw_characters(cd->termios_data, buf, i);

    /* dequeue transmitted chars */
    if (ERC32_MEC.UART_Status & ERC32_MEC_UART_STATUS_THEB) {
      rv = rtems_termios_dequeue_characters(
         cd->termios_data, chars_to_dequeue);
      if ( !rv ) {
        cd->pDeviceContext = 0;
        cd->bActive = false;
      }
      ERC32_Clear_interrupt (ERC32_INTERRUPT_UART_B_RX_TX);
    }
  } while (ERC32_Is_interrupt_pending (ERC32_INTERRUPT_UART_B_RX_TX));
}
static void
m8xx_smc2_interrupt_handler (void *unused)
{
    int nb_overflow;

    /*
     * Buffer received?
     */
    if (m8xx.smc2.smce & M8xx_SMCE_RX) {
        m8xx.smc2.smce = M8xx_SMCE_RX;  /* Clear the event */


        /* Check that the buffer is ours */
        if ((RxBd[SMC2_MINOR]->status & M8xx_BD_EMPTY) == 0) {
            rtems_cache_invalidate_multiple_data_lines(
                (const void *) RxBd[SMC2_MINOR]->buffer,
                RxBd[SMC2_MINOR]->length );
            nb_overflow = rtems_termios_enqueue_raw_characters(
                              (void *)ttyp[SMC2_MINOR],
                              (char *)RxBd[SMC2_MINOR]->buffer,
                              (int)RxBd[SMC2_MINOR]->length );
            RxBd[SMC2_MINOR]->status = M8xx_BD_EMPTY | M8xx_BD_WRAP |
                                       M8xx_BD_INTERRUPT;
        }
    }

    /*
     * Buffer transmitted?
     */
    if (m8xx.smc2.smce & M8xx_SMCE_TX) {
        m8xx.smc2.smce = M8xx_SMCE_TX;    /* Clear the event */

        /* Check that the buffer is ours */
        if ((TxBd[SMC2_MINOR]->status & M8xx_BD_READY) == 0)
            rtems_termios_dequeue_characters (
                (void *)ttyp[SMC2_MINOR],
                (int)TxBd[SMC2_MINOR]->length);
    }
}
Exemplo n.º 18
0
static void mpc55xx_esci_interrupt_handler(void *arg)
{
  mpc55xx_esci_context *self = arg;
  volatile struct ESCI_tag *regs = self->regs;
  union ESCI_SR_tag sr = MPC55XX_ZERO_FLAGS;
  union ESCI_SR_tag active = MPC55XX_ZERO_FLAGS;
  rtems_interrupt_level level;

  /* Status */
  sr.R = regs->SR.R;

  /* Receive data register full? */
  if (sr.B.RDRF != 0) {
    active.B.RDRF = 1;
  }

  /* Transmit data register empty? */
  if (sr.B.TDRE != 0) {
    active.B.TDRE = 1;
  }

  /* Clear flags */
  rtems_interrupt_disable(level);
  regs->SR.R = active.R;
  self->transmit_in_progress = false;
  rtems_interrupt_enable(level);

  /* Enqueue */
  if (active.B.RDRF != 0) {
    char c = regs->DR.B.D;
    rtems_termios_enqueue_raw_characters(self->tty, &c, 1);
  }

  /* Dequeue */
  if (active.B.TDRE != 0) {
    rtems_termios_dequeue_characters(self->tty, 1);
  }
}
Exemplo n.º 19
0
rtems_isr
m860_smc1_console_interrupt_handler (rtems_vector_number v)
{
  /*
   * Buffer received?
   */
  if (m860.smc1.smce & 0x1) {
    m860.smc1.smce = 0x1;
    /*    m860.scc2.sccm &= ~0x1;*/
    
    while ((RxBd[SMC1_MINOR]->status & M860_BD_EMPTY) == 0) {
      rxBufListTail[SMC1_MINOR]->next = malloc(sizeof(Buf_t));
      if (rxBufListTail[SMC1_MINOR]->next) {
        rxBufListTail[SMC1_MINOR] = rxBufListTail[SMC1_MINOR]->next;
        rxBufListTail[SMC1_MINOR]->buf = RxBd[SMC1_MINOR]->buffer;
        rxBufListTail[SMC1_MINOR]->len = RxBd[SMC1_MINOR]->length;
        rxBufListTail[SMC1_MINOR]->pos = 0;
        rxBufListTail[SMC1_MINOR]->next = 0;

        RxBd[SMC1_MINOR]->buffer = malloc(RXBUFSIZE);
      }
      RxBd[SMC1_MINOR]->status = M860_BD_EMPTY | M860_BD_WRAP | 
                                 M860_BD_INTERRUPT;
    }
  }
  
  /*
   * Buffer transmitted?
   */
#if 0
  if (m860.smc1.smce & 0x2) {
    m860.smc1.smce = 0x2;
    if ((smcTxBd->status & M360_BD_READY) == 0)
      rtems_termios_dequeue_characters (smc1ttyp, smcTxBd->length);
  }
#endif
  m860.cisr = 1UL << 4;  /* Clear SMC1 interrupt-in-service bit */
}
Exemplo n.º 20
0
/* Handle UART interrupts */
static void leon3_console_isr(void *arg)
{
  struct apbuart_priv *uart = arg;
  unsigned int status;
  char data;

  /* Get all received characters */
  while ((status=uart->regs->status) & LEON_REG_UART_STATUS_DR) {
    /* Data has arrived, get new data */
    data = uart->regs->data;

    /* Tell termios layer about new character */
    rtems_termios_enqueue_raw_characters(uart->cookie, &data, 1);
  }

  if (
    (status & LEON_REG_UART_STATUS_THE)
      && (uart->regs->ctrl & LEON_REG_UART_CTRL_TI) != 0
  ) {
    /* write_interrupt will get called from this function */
    rtems_termios_dequeue_characters(uart->cookie, 1);
  }
}
Exemplo n.º 21
0
/**
 * @brief Process interrupt.
 */
NS16550_STATIC void ns16550_process( int minor)
{
  console_tbl *c = Console_Port_Tbl [minor];
  console_data *d = &Console_Port_Data [minor];
  NS16550Context *ctx = d->pDeviceContext;
  uint32_t port = c->ulCtrlPort1;
  getRegister_f get = c->getRegister;
  int i;
  char buf [SP_FIFO_SIZE];

  /* Iterate until no more interrupts are pending */
  do {
    /* Fetch received characters */
    i = 0;
    while ((get(port, NS16550_LINE_STATUS) & SP_LSR_RDY) != 0) {
      buf[i++] = (char) get(port, NS16550_RECEIVE_BUFFER);
      if (i == SP_FIFO_SIZE) {
        /* Enqueue fetched characters */
        rtems_termios_enqueue_raw_characters( d->termios_data, buf, i);
        i = 0;
      }
    }

    if (i > 0)
      rtems_termios_enqueue_raw_characters( d->termios_data, buf, i);

    /* Check if we can dequeue transmitted characters */
    if (ctx->transmitFifoChars > 0
        && (get( port, NS16550_LINE_STATUS) & SP_LSR_THOLD) != 0) {
      /* Dequeue transmitted characters */
      rtems_termios_dequeue_characters(
        d->termios_data,
        ctx->transmitFifoChars
      );
    }
  } while ((get( port, NS16550_INTERRUPT_ID) & SP_IID_0) == 0);
}
Exemplo n.º 22
0
static void apbuart_isr(void *arg)
{
  rtems_termios_tty *tty = arg;
  struct apbuart_context *uart = rtems_termios_get_device_context(tty);
  unsigned int status;
  char data;

  /* Get all received characters */
  while ((status=uart->regs->status) & APBUART_STATUS_DR) {
    /* Data has arrived, get new data */
    data = uart->regs->data;

    /* Tell termios layer about new character */
    rtems_termios_enqueue_raw_characters(tty, &data, 1);
  }

  if (
    (status & APBUART_STATUS_TE)
      && (uart->regs->ctrl & APBUART_CTRL_TI) != 0
  ) {
    /* write_interrupt will get called from this function */
    rtems_termios_dequeue_characters(tty, 1);
  }
}
Exemplo n.º 23
0
/***************************************************************************
   Function : IntUartInterruptHandler

   Description : This is the interrupt handler for the internal uart. It
   determines which channel caused the interrupt before queueing any received
   chars and dequeueing chars waiting for transmission.
 ***************************************************************************/
static rtems_isr
IntUartInterruptHandler(rtems_vector_number v)
{
	unsigned int                chan = v - UART_INTC0_IRQ_VECTOR(0);
	struct IntUartInfoStruct   *info = &IntUartInfo[chan];

	/* check to see if received data */
	if ( MCF5282_UART_UISR(chan) & MCF5282_UART_UISR_RXRDY )
	{
		/* read data and put into the receive buffer */
		while ( MCF5282_UART_USR(chan) & MCF5282_UART_USR_RXRDY )
		{

			if ( MCF5282_UART_USR(chan) & MCF5282_UART_USR_ERROR )
			{
				/* clear the error */
				MCF5282_UART_UCR(chan) = MCF5282_UART_UCR_RESET_ERROR;
			}
			/* put data in rx buffer and check for errors */
			info->rx_buffer[info->rx_in] = MCF5282_UART_URB(chan);

			/* update buffer values */
			info->rx_in++;

			if ( info->rx_in >= RX_BUFFER_SIZE )
			{
				info->rx_in = 0;
			}
		}
		/* Make sure the port has been opened */
		if ( info->ttyp )
		{

			/* check to see if task driven */
			if ( info->iomode == TERMIOS_TASK_DRIVEN )
			{
				/* notify rx task that rx buffer has data */
				rtems_termios_rxirq_occured(info->ttyp);
			}
			else
			{
				/* Push up the received data */
				rtems_termios_enqueue_raw_characters(info->ttyp, info->rx_buffer, info->rx_in);
				info->rx_in    = 0;
			}
		}
	}

	/* check to see if data needs to be transmitted */
	if ( ( info->uimr & MCF5282_UART_UIMR_TXRDY ) &&
		 ( MCF5282_UART_UISR(chan) & MCF5282_UART_UISR_TXRDY ) )
	{

		/* disable tx interrupts */
		info->uimr &= ~MCF5282_UART_UIMR_TXRDY;
		MCF5282_UART_UIMR(chan) = info->uimr;

		/* tell upper level that character has been sent */
		if ( info->ttyp )
			rtems_termios_dequeue_characters(info->ttyp, 1);
	}
}
Exemplo n.º 24
0
Arquivo: uart.c Projeto: RTEMS/rtems
void
BSP_uart_termios_isr_com2(void *ignored)
{
  unsigned char buf[40];
  unsigned char val;
  int      off, ret, vect;

  off = 0;

  for(;;)
    {
      vect = uread(BSP_UART_COM2, IIR) & 0xf;

      switch(vect)
	{
	case MODEM_STATUS :
	  val = uread(BSP_UART_COM2, MSR);
	  if(uart_data[BSP_UART_COM2].hwFlow)
	    {
	      if(val & CTS)
		{
		  /* CTS high */
		  termios_stopped_com2 = 0;
		  if(termios_tx_hold_valid_com2)
		    {
		      termios_tx_hold_valid_com2 = 0;
		      BSP_uart_termios_write_com2(0, &termios_tx_hold_com2,
						    1);
		    }
		}
	      else
		{
		  /* CTS low */
		  termios_stopped_com2 = 1;
		}
	    }
	  break;
	case NO_MORE_INTR :
	  /* No more interrupts */
	  if(off != 0)
	    {
	      /* Update rx buffer */
         if( driver_input_handler_com2 )
         {
             driver_input_handler_com2( termios_ttyp_com2, (char *)buf, off );
         }
         else
         {
	        rtems_termios_enqueue_raw_characters(termios_ttyp_com2, (char *)buf, off);
         }
	    }
	  return;
	case TRANSMITTER_HODING_REGISTER_EMPTY :
	  /*
	   * TX holding empty: we have to disable these interrupts
	   * if there is nothing more to send.
	   */

	  /* If nothing else to send disable interrupts */
	  ret = rtems_termios_dequeue_characters(termios_ttyp_com2, 1);
          if ( ret == 0 ) {
            termios_tx_active_com2 = 0;
            uart_data[BSP_UART_COM2].ier &= ~(TRANSMIT_ENABLE);
            uwrite(BSP_UART_COM2, IER, uart_data[BSP_UART_COM2].ier);
          }
	  break;
	case RECEIVER_DATA_AVAIL :
	case CHARACTER_TIMEOUT_INDICATION:
          if ( uart_data[BSP_UART_COM2].ioMode == TERMIOS_TASK_DRIVEN ) {
            /* ensure interrupts are enabled */
            if ( uart_data[BSP_UART_COM2].ier & RECEIVE_ENABLE ) {
              /* disable interrupts and notify termios */
              uart_data[BSP_UART_COM2].ier &= ~(RECEIVE_ENABLE | RECEIVER_LINE_ST_ENABLE);
              uwrite(BSP_UART_COM2, IER, uart_data[BSP_UART_COM2].ier);
              rtems_termios_rxirq_occured(termios_ttyp_com2);
            }
          }
          else {
	    /* RX data ready */
	    assert(off < sizeof(buf));
	    buf[off++] = uread(BSP_UART_COM2, RBR);
          }
	  break;
	case RECEIVER_ERROR:
	  /* RX error: eat character */
	   uartError(BSP_UART_COM2);
	  break;
	default:
	  /* Should not happen */
	  assert(0);
	  return;
	}
    }
}
Exemplo n.º 25
0
/*
 * Interrupt handler
 */
static rtems_isr
sccInterruptHandler (void *arg)
{
  int chan = (int)arg;

  /*
   * Buffer received?
   */
  if (CHN_EVENT_GET(chan) & 0x1) {
    /*
     * clear SCC event flag
     */
    CHN_EVENT_CLR(chan,0x01);
    /*
     * process event
     */
    while ((sccCurrRxBd[chan]->status & M8xx_BD_EMPTY) == 0) {
      if (sccttyp[chan] != NULL) {
	rtems_cache_invalidate_multiple_data_lines((void *)sccCurrRxBd[chan]->buffer,
						   sccCurrRxBd[chan]->length);
	rtems_termios_enqueue_raw_characters (sccttyp[chan],
					      (char *)sccCurrRxBd[chan]->buffer,
					      sccCurrRxBd[chan]->length);
      }
      /*
       * clear status
       */
      sccCurrRxBd[chan]->status =
	(sccCurrRxBd[chan]->status
	 & (M8xx_BD_WRAP | M8xx_BD_INTERRUPT))
	| M8xx_BD_EMPTY;
      /*
       * advance to next BD
       */
      if ((sccCurrRxBd[chan]->status & M8xx_BD_WRAP) != 0) {
	sccCurrRxBd[chan] = sccFrstRxBd[chan];
      }
      else {
	sccCurrRxBd[chan]++;
      }
    }
  }
  /*
   * Buffer transmitted?
   */
  if (CHN_EVENT_GET(chan) & 0x2) {
    /*
     * then clear interrupt event bit
     */
    CHN_EVENT_CLR(chan,0x2);
    /*
     * and signal successful transmit to termios
     */
    /*
     * FIXME: multiple dequeue calls for multiple buffers
     */
    while((sccDequTxBd[chan] != sccPrepTxBd[chan]) &&
	  ((sccDequTxBd[chan]->status & M8xx_BD_READY) == 0)) {
      if (sccttyp[chan] != NULL) {
	rtems_termios_dequeue_characters (sccttyp[chan],
					  sccDequTxBd[chan]->length);
      }
      /*
       * advance to next BD
       */
      if ((sccDequTxBd[chan]->status & M8xx_BD_WRAP) != 0) {
	sccDequTxBd[chan] = sccFrstTxBd[chan];
      }
      else {
	sccDequTxBd[chan]++;
      }
    }
  }
}
Exemplo n.º 26
0
Z85C30_STATIC void z85c30_process(
  int        minor,
  uint8_t    ucIntPend
)
{
  uint32_t            ulCtrlPort;
  volatile uint8_t    z85c30_status;
  char                cChar;
  setRegister_f       setReg;
  getRegister_f       getReg;

  ulCtrlPort = Console_Port_Tbl[minor].ulCtrlPort1;
  setReg     = Console_Port_Tbl[minor].setRegister;
  getReg     = Console_Port_Tbl[minor].getRegister;

  /*
   * Deal with any received characters
   */

  while (ucIntPend&SCC_RR3_B_RX_IP)
  {
    z85c30_status = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0);
    if (!Z85C30_Status_Is_RX_character_available(z85c30_status)) {
      break;
    }

    /*
     * Return the character read.
     */

    cChar = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD8);

    rtems_termios_enqueue_raw_characters(
      Console_Port_Data[minor].termios_data,
      &cChar,
      1
    );
  }

  /*
   *  There could be a race condition here if there is not yet a TX
   *  interrupt pending but the buffer is empty.  This condition has
   *  been seen before on other z8530 drivers but has not been seen
   *  with this one.  The typical solution is to use "vector includes
   *  status" or to only look at the interrupts actually pending
   *  in RR3.
   */

  while (true) {
    z85c30_status = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0);
    if (!Z85C30_Status_Is_TX_buffer_empty(z85c30_status)) {
      /*
       * We'll get another interrupt when
       * the transmitter holding reg. becomes
       * free again and we are clear to send
       */
      break;
    }

#if 0
    if (!Z85C30_Status_Is_CTS_asserted(z85c30_status)) {
      /*
       * We can't transmit yet
       */
      (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_TX_INT);
      /*
       * The next state change of CTS will wake us up
       */
      break;
    }
#endif

    rtems_termios_dequeue_characters(Console_Port_Data[minor].termios_data, 1);
    if (rtems_termios_dequeue_characters(
         Console_Port_Data[minor].termios_data, 1)) {
      if (Console_Port_Tbl[minor].pDeviceFlow != &z85c30_flow_RTSCTS) {
        z85c30_negate_RTS(minor);
      }
      Console_Port_Data[minor].bActive = FALSE;
      z85c30_enable_interrupts(minor, SCC_ENABLE_ALL_INTR_EXCEPT_TX);
      (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_TX_INT);
      break;
    }

  }

  if (ucIntPend & SCC_RR3_B_EXT_IP) {
    /*
     * Clear the external status interrupt
     */
    (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_INT);
    z85c30_status = (*getReg)(ulCtrlPort, SCC_WR0_SEL_RD0);
  }

  /*
   * Reset interrupts
   */
  (*setReg)(ulCtrlPort, SCC_WR0_SEL_WR0, SCC_WR0_RST_HI_IUS);
}
Exemplo n.º 27
0
/******************************************************
  Name: InterruptHandler
  Input parameters: vector number
  Output parameters: -
  Description: UART ISR Routine, called by _RTEMS_ISR
 *****************************************************/
rtems_isr
InterruptHandler (rtems_vector_number v)
{
 char ch;

 /*****************************************************************************
 **				CHANNEL A				     **
 *****************************************************************************/

    /* check Received Break*/
    if (DUSRA & m340_RB) {
       Error_Status_A |= m340_RB;
       /* reset error status */
       DUCRA = m340_Reset_Error_Status;
    }

    /* buffer received ? */
    if (DUSRA & m340_Rx_RDY) {
       do {
	   /* error encountered? */
	   if (DUSRA & (m340_OE | m340_PE | m340_FE | m340_RB)) {
	      Error_Status_A |= DUSRA;
	      /* reset error status */
    	      DUCRA = m340_Reset_Error_Status;
	      /* all the characters in the queue may not be good */
	      while (DUSRA & m340_Rx_RDY)
		    /* push them in a trash */
		    ch = DURBA;
	   }
	   else {
		 /* this is necessary, otherwise it blocks when FIFO is full */
		 ch = DURBA;
		 rtems_termios_enqueue_raw_characters(ttypA,&ch,1);
	   }
       } while (DUSRA & m340_Rx_RDY);
       Restart_Fifo_Full_A_Timer();	/* only if necessary (pointer to a fake function if
					   not in FIFO full mode) */
    }

    else /* if no character has been received */
       Restart_Check_A_Timer();		/* same remark */

    /* ready to accept a character ? */
    if (DUISR & DUIER_mirror & m340_TxRDYA) {
	Disable_Interrupts_Tx_A;
	/* one character has been transmitted */
	rtems_termios_dequeue_characters(ttypA,1);
    }

 /*****************************************************************************
 **				CHANNEL B				     **
 *****************************************************************************/

    /* check Received Break*/
    if (DUSRB & m340_RB) {
       Error_Status_B |= m340_RB;
       /* reset error status */
       DUCRB = m340_Reset_Error_Status;
    }

    /* buffer received ? */
    if (DUSRB & m340_Rx_RDY) {
       do {
	   if (DUSRB & (m340_OE | m340_PE | m340_FE | m340_RB)) {
	      Error_Status_B |= DUSRB;
	      /* reset error status */
    	      DUCRB = m340_Reset_Error_Status;
	      /* all the characters in the queue may not be good */
	      while (DUSRB & m340_Rx_RDY)
		    /* push them in a trash */
		    ch = DURBB;
	   }
	   else {
		 ch = DURBB;
		 rtems_termios_enqueue_raw_characters(ttypB,&ch,1);
	   }

       } while (DUSRB & m340_Rx_RDY);
       Restart_Fifo_Full_B_Timer();
    }
    else /* if no character has been received */
       Restart_Check_B_Timer();

    /* ready to accept a character ? */
    if (DUISR & DUIER_mirror & m340_TxRDYB) {
	Disable_Interrupts_Tx_B;
	/* one character has been transmitted */
	rtems_termios_dequeue_characters(ttypB,1);
    }
}