forked from Imagelibrary/rtems
710 lines
20 KiB
C
710 lines
20 KiB
C
/* SPDX-License-Identifier: BSD-2-Clause */
|
|
|
|
/*
|
|
* 68340/68349 console serial I/O.
|
|
*/
|
|
|
|
/*
|
|
* Author:
|
|
* Geoffroy Montel
|
|
* France Telecom - CNET/DSM/TAM/CAT
|
|
* 4, rue du Clos Courtel
|
|
* 35512 CESSON-SEVIGNE
|
|
* FRANCE
|
|
*
|
|
* e-mail: g_montel@yahoo.com
|
|
*
|
|
* COPYRIGHT (c) 1989-1999.
|
|
* On-Line Applications Research Corporation (OAR).
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#include <termios.h>
|
|
|
|
#include <stdarg.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
#include <bsp.h>
|
|
#include <rtems/libio.h>
|
|
#include <rtems/termiostypes.h>
|
|
#include <rtems/console.h>
|
|
#include <m68340.h>
|
|
#include <m340uart.h>
|
|
#include <m340timer.h>
|
|
|
|
#define CONSOLE_VECTOR 121
|
|
#define CONSOLE_IRQ_LEVEL 3
|
|
#define CONSOLE_INTERRUPT_ARBITRATION 2
|
|
|
|
static void *ttypA; /* to remember which tty has been opened on channel A
|
|
used when interrupts are enabled */
|
|
|
|
static void *ttypB; /* to remember which tty has been opened on channel B
|
|
used when interrupts are enabled */
|
|
|
|
unsigned char DUIER_mirror = 0 ; /* reflects the state of IER register, which is Write Only */
|
|
unsigned char Error_Status_A = 0; /* error status on Channel A */
|
|
unsigned char Error_Status_B = 0; /* error status on Channel A */
|
|
|
|
/*
|
|
* Device-specific routines
|
|
*/
|
|
|
|
#define USE_INTERRUPTS_A (m340_uart_config[UART_CHANNEL_A].mode==UART_INTERRUPTS)
|
|
#define USE_INTERRUPTS_B (m340_uart_config[UART_CHANNEL_B].mode==UART_INTERRUPTS)
|
|
#define CHANNEL_ENABLED_A m340_uart_config[UART_CHANNEL_A].enable
|
|
#define CHANNEL_ENABLED_B m340_uart_config[UART_CHANNEL_B].enable
|
|
|
|
#define set_DUIER(a) DUIER_mirror |= (a); DUIER = DUIER_mirror
|
|
#define unset_DUIER(a) DUIER_mirror &= ~(a); DUIER = DUIER_mirror
|
|
|
|
#define Enable_Interrupts_Tx_A if (USE_INTERRUPTS_A) set_DUIER(m340_TxRDYA)
|
|
#define Disable_Interrupts_Tx_A if (USE_INTERRUPTS_A) unset_DUIER(m340_TxRDYA)
|
|
|
|
#define Enable_Interrupts_Tx_B if (USE_INTERRUPTS_B) set_DUIER(m340_TxRDYB)
|
|
#define Disable_Interrupts_Tx_B if (USE_INTERRUPTS_B) unset_DUIER(m340_TxRDYB)
|
|
|
|
/******************************************************
|
|
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);
|
|
}
|
|
}
|
|
|
|
/******************************************************
|
|
Name: InterruptWrite
|
|
Input parameters: minor = channel, pointer to buffer,
|
|
and length of buffer to transmit
|
|
Output parameters: -
|
|
Description: write the first character of buf only
|
|
may be called by either console_write
|
|
or rtems_termios_enqueue_raw_characters
|
|
*****************************************************/
|
|
static ssize_t
|
|
InterruptWrite (int minor, const char *buf, size_t len)
|
|
{
|
|
if (minor==UART_CHANNEL_A) {
|
|
if (len>0) {
|
|
DUTBA=*buf;
|
|
Enable_Interrupts_Tx_A;
|
|
}
|
|
}
|
|
else if (minor==UART_CHANNEL_B) {
|
|
if (len>0) {
|
|
DUTBB=*buf;
|
|
Enable_Interrupts_Tx_B;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/******************************************************
|
|
Name: dbug_out_char
|
|
Input parameters: channel, character to emit
|
|
Output parameters: -
|
|
Description: wait for the UART to be ready to emit
|
|
a character and send it
|
|
*****************************************************/
|
|
void dbug_out_char( int minor, int ch )
|
|
{
|
|
if (minor==UART_CHANNEL_A) {
|
|
while (!(DUSRA & m340_Tx_RDY)) continue;
|
|
DUTBA=ch;
|
|
}
|
|
else if (minor==UART_CHANNEL_B) {
|
|
while (!(DUSRB & m340_Tx_RDY)) continue;
|
|
DUTBB=ch;
|
|
}
|
|
}
|
|
|
|
/******************************************************
|
|
Name: dbug_in_char
|
|
Input parameters: -
|
|
Output parameters: received character
|
|
Description: return the character in the UART
|
|
*****************************************************/
|
|
int dbug_in_char( int minor )
|
|
{
|
|
if (minor==UART_CHANNEL_A) {
|
|
return DURBA;
|
|
}
|
|
else if (minor==UART_CHANNEL_B) {
|
|
return DURBB;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/******************************************************
|
|
Name: dbug_char_present
|
|
Input parameters: channel #
|
|
Output parameters: TRUE or FALSE
|
|
Description: return whether there's a character
|
|
in the receive buffer
|
|
*****************************************************/
|
|
int dbug_char_present( int minor )
|
|
{
|
|
if (minor==UART_CHANNEL_A) {
|
|
return (DUSRA & m340_Rx_RDY);
|
|
}
|
|
else if (minor==UART_CHANNEL_B) {
|
|
return (DUSRB & m340_Rx_RDY);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
/******************************************************
|
|
Name: dbugInitialise
|
|
Input parameters: -
|
|
Output parameters: -
|
|
Description: Init the UART
|
|
*****************************************************/
|
|
static void
|
|
dbugInitialise (void)
|
|
{
|
|
t_baud_speed_table uart_config; /* configuration of UARTS */
|
|
|
|
/*
|
|
* Reset Receiver
|
|
*/
|
|
DUCRA = m340_Reset_Receiver;
|
|
DUCRB = m340_Reset_Receiver;
|
|
|
|
/*
|
|
* Reset Transmitter
|
|
*/
|
|
DUCRA = m340_Reset_Transmitter;
|
|
DUCRB = m340_Reset_Transmitter;
|
|
|
|
/*
|
|
* Enable serial module for normal operation, ignore FREEZE, select the crystal clock,
|
|
* supervisor/user serial registers unrestricted
|
|
* interrupt arbitration at priority CONSOLE_INTERRUPT_ARBITRATION
|
|
* WARNING : 8 bits access only on this UART!
|
|
*/
|
|
DUMCRH = 0x00;
|
|
DUMCRL = CONSOLE_INTERRUPT_ARBITRATION;
|
|
|
|
/*
|
|
* Interrupt level register
|
|
*/
|
|
DUILR = CONSOLE_IRQ_LEVEL;
|
|
|
|
/* sets the IVR */
|
|
DUIVR = CONSOLE_VECTOR;
|
|
|
|
/* search for a correct m340 uart configuration */
|
|
uart_config = Find_Right_m340_UART_Config(m340_uart_config[UART_CHANNEL_A].rx_baudrate,
|
|
m340_uart_config[UART_CHANNEL_A].tx_baudrate,
|
|
CHANNEL_ENABLED_A,
|
|
m340_uart_config[UART_CHANNEL_B].rx_baudrate,
|
|
m340_uart_config[UART_CHANNEL_B].tx_baudrate,
|
|
CHANNEL_ENABLED_B);
|
|
|
|
/*****************************************************************************
|
|
** CHANNEL A **
|
|
*****************************************************************************/
|
|
if (CHANNEL_ENABLED_A) {
|
|
|
|
if (USE_INTERRUPTS_A) {
|
|
rtems_isr_entry old_handler;
|
|
|
|
(void) rtems_interrupt_catch (InterruptHandler,
|
|
CONSOLE_VECTOR,
|
|
&old_handler);
|
|
|
|
/* uncomment this if you want to pass control to your own ISR handler
|
|
it may be usefull to do so to check for performances with an oscilloscope */
|
|
/*
|
|
{
|
|
CPU_ISR_raw_handler ignored;
|
|
_CPU_ISR_install_raw_handler( CONSOLE_VECTOR, _Debug_ISR_Handler_Console, &ignored );
|
|
}
|
|
*/
|
|
|
|
/*
|
|
* Interrupt Enable Register
|
|
* Enable Interrupts on Channel A Receiver Ready
|
|
*/
|
|
set_DUIER(m340_RxRDYA);
|
|
}
|
|
else {
|
|
/*
|
|
* Disable Interrupts on channel A
|
|
*/
|
|
unset_DUIER(m340_RxRDYA&m340_TxRDYA);
|
|
}
|
|
|
|
/*
|
|
* Change set of baud speeds
|
|
* disable input control
|
|
*/
|
|
/* no good uart configuration ? */
|
|
if (uart_config.nb<1) rtems_fatal_error_occurred (-1);
|
|
|
|
if (uart_config.baud_speed_table[UART_CHANNEL_A].set==1)
|
|
DUACR = m340_BRG_Set1;
|
|
else
|
|
DUACR = m340_BRG_Set2;
|
|
|
|
/*
|
|
* make OPCR an auxiliary function serving the communication channels
|
|
*/
|
|
DUOPCR = m340_OPCR_Aux;
|
|
|
|
/* poll the XTAL_RDY bit until it is cleared to ensure that an unstable crystal
|
|
input is not applied to the baud rate generator */
|
|
while (DUISR & m340_XTAL_RDY) continue;
|
|
|
|
/*
|
|
* Serial Channel Baud Speed
|
|
*/
|
|
DUCSRA = (uart_config.baud_speed_table[UART_CHANNEL_A].rcs << 4)
|
|
| (uart_config.baud_speed_table[UART_CHANNEL_A].tcs);
|
|
|
|
/*
|
|
* Serial Channel Configuration
|
|
*/
|
|
DUMR1A = m340_uart_config[UART_CHANNEL_A].parity_mode
|
|
| m340_uart_config[UART_CHANNEL_A].bits_per_char
|
|
| m340_RxRTS;
|
|
|
|
if (m340_uart_config[UART_CHANNEL_A].rx_mode==UART_FIFO_FULL) DUMR1A |= m340_R_F | m340_ERR;
|
|
|
|
/*
|
|
* Serial Channel Configuration 2
|
|
*/
|
|
DUMR2A |= m340_normal;
|
|
|
|
/*
|
|
* Enable Channel A: transmitter and receiver
|
|
*/
|
|
DUCRA = m340_Transmitter_Enable | m340_Receiver_Enable;
|
|
} /* channel A enabled */
|
|
|
|
/*****************************************************************************
|
|
** CHANNEL B **
|
|
*****************************************************************************/
|
|
if (CHANNEL_ENABLED_B) {
|
|
|
|
/* we mustn't set the console vector twice! */
|
|
if ((USE_INTERRUPTS_B && !(CHANNEL_ENABLED_A))
|
|
|| (USE_INTERRUPTS_B && CHANNEL_ENABLED_A && !USE_INTERRUPTS_A)) {
|
|
rtems_isr_entry old_handler;
|
|
|
|
(void) rtems_interrupt_catch (InterruptHandler,
|
|
CONSOLE_VECTOR,
|
|
&old_handler);
|
|
|
|
/* uncomment this if you want to pass control to your own ISR handler
|
|
it may be usefull to do so to check for performances with an oscilloscope */
|
|
/*
|
|
{
|
|
CPU_ISR_raw_handler ignored;
|
|
_CPU_ISR_install_raw_handler( CONSOLE_VECTOR, _Debug_ISR_Handler_Console, &ignored );
|
|
}
|
|
*/
|
|
|
|
/*
|
|
* Interrupt Enable Register
|
|
* Enable Interrupts on Channel A Receiver Ready
|
|
*/
|
|
set_DUIER(m340_RxRDYB);
|
|
}
|
|
else {
|
|
/*
|
|
* Disable Interrupts on channel B
|
|
*/
|
|
unset_DUIER(m340_RxRDYB&m340_TxRDYB);
|
|
}
|
|
|
|
/*
|
|
* Change set of baud speeds
|
|
* disable input control
|
|
*/
|
|
|
|
/* no good uart configuration ? */
|
|
if (uart_config.nb<2) rtems_fatal_error_occurred (-1);
|
|
|
|
/* don't set DUACR twice! */
|
|
if (!CHANNEL_ENABLED_A) {
|
|
if (uart_config.baud_speed_table[UART_CHANNEL_B].set==1)
|
|
DUACR = m340_BRG_Set1;
|
|
else
|
|
DUACR = m340_BRG_Set2;
|
|
}
|
|
|
|
/*
|
|
* make OPCR an auxiliary function serving the communication channels
|
|
*/
|
|
if (!CHANNEL_ENABLED_A) DUOPCR = m340_OPCR_Aux;
|
|
|
|
/* poll the XTAL_RDY bit until it is cleared to ensure that an unstable crystal
|
|
input is not applied to the baud rate generator */
|
|
while (DUISR & m340_XTAL_RDY) continue;
|
|
|
|
/*
|
|
* Serial Channel Baud Speed
|
|
*/
|
|
DUCSRB = (uart_config.baud_speed_table[UART_CHANNEL_B].rcs << 4)
|
|
| (uart_config.baud_speed_table[UART_CHANNEL_B].tcs);
|
|
|
|
/*
|
|
* Serial Channel Configuration
|
|
*/
|
|
DUMR1B = m340_uart_config[UART_CHANNEL_B].parity_mode
|
|
| m340_uart_config[UART_CHANNEL_B].bits_per_char
|
|
| m340_RxRTS;
|
|
|
|
if (m340_uart_config[UART_CHANNEL_B].rx_mode==UART_FIFO_FULL) DUMR1B |= m340_R_F | m340_ERR;
|
|
|
|
/*
|
|
* Serial Channel Configuration 2
|
|
*/
|
|
DUMR2B |= m340_normal;
|
|
|
|
/*
|
|
* Enable Channel A: transmitter and receiver
|
|
*/
|
|
DUCRB = m340_Transmitter_Enable | m340_Receiver_Enable;
|
|
} /* channel B enabled */
|
|
}
|
|
|
|
/******************************************************
|
|
Name: SetAttributes
|
|
Input parameters: termios structure, channel
|
|
Output parameters: -
|
|
Description: return whether there's a character
|
|
in the receive buffer
|
|
TO DO: add the channel # to check for!!
|
|
*****************************************************/
|
|
static int
|
|
SetAttributes (int minor, const struct termios *t)
|
|
{
|
|
rtems_interrupt_level level;
|
|
float ispeed, ospeed;
|
|
|
|
/* convert it */
|
|
ispeed = rtems_termios_baud_to_number(t->c_ispeed);
|
|
ospeed = rtems_termios_baud_to_number(t->c_ospeed);
|
|
|
|
if (ispeed || ospeed) {
|
|
/* update config table */
|
|
m340_uart_config[UART_CHANNEL_A].rx_baudrate = ((minor==UART_CHANNEL_A)&&(ispeed!=0)) ? ispeed : m340_uart_config[UART_CHANNEL_A].rx_baudrate;
|
|
m340_uart_config[UART_CHANNEL_A].tx_baudrate = ((minor==UART_CHANNEL_A)&&(ospeed!=0)) ? ospeed : m340_uart_config[UART_CHANNEL_A].tx_baudrate;
|
|
m340_uart_config[UART_CHANNEL_B].rx_baudrate = ((minor==UART_CHANNEL_B)&&(ispeed!=0)) ? ispeed : m340_uart_config[UART_CHANNEL_B].rx_baudrate;
|
|
m340_uart_config[UART_CHANNEL_B].tx_baudrate = ((minor==UART_CHANNEL_B)&&(ospeed!=0)) ? ospeed : m340_uart_config[UART_CHANNEL_B].tx_baudrate;
|
|
}
|
|
|
|
/* change parity */
|
|
if (t->c_cflag & PARENB) {
|
|
if (t->c_cflag & PARODD) m340_uart_config[minor].parity_mode = m340_Odd_Parity;
|
|
else m340_uart_config[minor].parity_mode = m340_Even_Parity;
|
|
}
|
|
|
|
/* change bits per character */
|
|
if (t->c_cflag & CSIZE) {
|
|
switch (t->c_cflag & CSIZE) {
|
|
default: break;
|
|
case CS5: m340_uart_config[minor].bits_per_char = m340_5bpc; break;
|
|
case CS6: m340_uart_config[minor].bits_per_char = m340_6bpc; break;
|
|
case CS7: m340_uart_config[minor].bits_per_char = m340_7bpc; break;
|
|
case CS8: m340_uart_config[minor].bits_per_char = m340_8bpc; break;
|
|
}
|
|
}
|
|
|
|
/* if serial module configuration has been changed */
|
|
if (t->c_cflag & (CSIZE | PARENB)) {
|
|
rtems_interrupt_disable(level);
|
|
/* reinit the UART */
|
|
dbugInitialise();
|
|
rtems_interrupt_enable (level);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
/******************************************************
|
|
Name: console_initialize
|
|
Input parameters: MAJOR # of console_driver,
|
|
minor is always 0,
|
|
args are always NULL
|
|
Output parameters: -
|
|
Description: Reserve resources consumed by this driver
|
|
TODO: We should pass m340_uart_config table in arg
|
|
*****************************************************/
|
|
rtems_device_driver console_initialize(
|
|
rtems_device_major_number major,
|
|
rtems_device_minor_number minor,
|
|
void *arg
|
|
)
|
|
{
|
|
rtems_status_code status;
|
|
int i;
|
|
|
|
/*
|
|
* Set up TERMIOS
|
|
*/
|
|
rtems_termios_initialize ();
|
|
|
|
/*
|
|
* Do device-specific initialization
|
|
*/
|
|
Init_UART_Table();
|
|
dbugInitialise ();
|
|
Fifo_Full_benchmark_timer_initialize();
|
|
|
|
/*
|
|
* Register the devices
|
|
*/
|
|
for (i=0; i<UART_NUMBER_OF_CHANNELS; i++) {
|
|
if (m340_uart_config[i].enable) {
|
|
status = rtems_io_register_name (m340_uart_config[i].name, major, i);
|
|
if (status != RTEMS_SUCCESSFUL)
|
|
rtems_fatal_error_occurred (status);
|
|
}
|
|
}
|
|
|
|
return RTEMS_SUCCESSFUL;
|
|
}
|
|
|
|
/******************************************************
|
|
Name: console_open
|
|
Input parameters: channel #, arg
|
|
Output parameters: -
|
|
Description: open the device
|
|
*****************************************************/
|
|
rtems_device_driver console_open(
|
|
rtems_device_major_number major,
|
|
rtems_device_minor_number minor,
|
|
void * arg
|
|
)
|
|
{
|
|
rtems_status_code sc = 0;
|
|
|
|
static const rtems_termios_callbacks intrCallbacks = {
|
|
NULL, /* firstOpen */
|
|
NULL, /* lastClose */
|
|
NULL, /* pollRead */
|
|
InterruptWrite, /* write */
|
|
SetAttributes, /* setAttributes */
|
|
NULL, /* stopRemoteTx */
|
|
NULL, /* startRemoteTx */
|
|
1 /* outputUsesInterrupts */
|
|
};
|
|
|
|
static const rtems_termios_callbacks pollCallbacks = {
|
|
NULL, /* firstOpen */
|
|
NULL, /* lastClose */
|
|
dbugRead, /* pollRead */
|
|
dbugWrite, /* write */
|
|
SetAttributes, /* setAttributes */
|
|
NULL, /* stopRemoteTx */
|
|
NULL, /* startRemoteTx */
|
|
0 /* outputUsesInterrupts */
|
|
};
|
|
|
|
if (minor==UART_CHANNEL_A) {
|
|
if (USE_INTERRUPTS_A) {
|
|
rtems_libio_open_close_args_t *args = arg;
|
|
|
|
sc |= rtems_termios_open (major, minor, arg, &intrCallbacks);
|
|
ttypA = args->iop->data1;
|
|
}
|
|
else {
|
|
sc |= rtems_termios_open (major, minor, arg, &pollCallbacks);
|
|
}
|
|
}
|
|
|
|
else if (minor==UART_CHANNEL_B) {
|
|
if (USE_INTERRUPTS_B) {
|
|
rtems_libio_open_close_args_t *args = arg;
|
|
|
|
sc |= rtems_termios_open (major, minor, arg, &intrCallbacks);
|
|
ttypB = args->iop->data1;
|
|
}
|
|
else {
|
|
sc |= rtems_termios_open (major, minor, arg, &pollCallbacks);
|
|
}
|
|
}
|
|
|
|
else return RTEMS_INVALID_NUMBER;
|
|
|
|
return sc;
|
|
}
|
|
|
|
/******************************************************
|
|
Name: console_close
|
|
Input parameters: channel #, termios args
|
|
Output parameters: -
|
|
Description: close the device
|
|
*****************************************************/
|
|
rtems_device_driver console_close(
|
|
rtems_device_major_number major,
|
|
rtems_device_minor_number minor,
|
|
void * arg
|
|
)
|
|
{
|
|
return rtems_termios_close (arg);
|
|
}
|
|
|
|
/******************************************************
|
|
Name: console_read
|
|
Input parameters: channel #, termios args
|
|
Output parameters: -
|
|
Description: read the device
|
|
*****************************************************/
|
|
rtems_device_driver console_read(
|
|
rtems_device_major_number major,
|
|
rtems_device_minor_number minor,
|
|
void * arg
|
|
)
|
|
{
|
|
return rtems_termios_read (arg);
|
|
}
|
|
|
|
/******************************************************
|
|
Name: console_write
|
|
Input parameters: channel #, termios args
|
|
Output parameters: -
|
|
Description: write to the device
|
|
*****************************************************/
|
|
rtems_device_driver console_write(
|
|
rtems_device_major_number major,
|
|
rtems_device_minor_number minor,
|
|
void * arg
|
|
)
|
|
{
|
|
return rtems_termios_write (arg);
|
|
}
|
|
|
|
/******************************************************
|
|
Name: console_control
|
|
Input parameters: channel #, termios args
|
|
Output parameters: -
|
|
Description: Handle ioctl request
|
|
*****************************************************/
|
|
rtems_device_driver console_control(
|
|
rtems_device_major_number major,
|
|
rtems_device_minor_number minor,
|
|
void * arg
|
|
)
|
|
{
|
|
rtems_libio_ioctl_args_t *args = arg;
|
|
|
|
if (args->command == TIOCSETA)
|
|
SetAttributes (minor, (struct termios *)args->buffer);
|
|
|
|
return rtems_termios_ioctl (arg);
|
|
}
|