/* * 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; } } }
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; } } }
/** * @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); } } }
/* * 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); } } }
/* * 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 */ }
/* 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); } }
/* 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); } }
/* 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); } }
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 ); }
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); }
/** * @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); }
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); } }
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); } }
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); } }
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); }
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); } }
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); } }
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 */ }
/* 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); } }
/** * @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); }
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); } }
/*************************************************************************** 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); } }
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; } } }
/* * 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]++; } } } }
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); }
/****************************************************** 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); } }