mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2025-12-13 19:35:21 +08:00
Add "(void) param;" annotation to address unused parameter warnings. Found with GCC's warning -Wunused-parameter.
477 lines
13 KiB
C
477 lines
13 KiB
C
/*
|
|
* This file contains the MBX8xx termios serial I/O package.
|
|
* Only asynchronous I/O is supported.
|
|
*
|
|
* The SCCs and SMCs are assigned as follows
|
|
*
|
|
* Channel Device Minor Note
|
|
* SMC1 /dev/tty0 0
|
|
* SMC2 /dev/tty1 1
|
|
* SCC1 2 N/A. Hardwired as ethernet port
|
|
* SCC2 /dev/tty2 3
|
|
* SCC3 /dev/tty3 4
|
|
* SCC4 /dev/tty4 5
|
|
*
|
|
* The SCCs and SMCs on the eval board are assigned as follows
|
|
*
|
|
* Channel Device Minor Termios
|
|
* SMC1 /dev/tty3 4 no
|
|
* SMC2 /dev/tty4 5 no
|
|
* SCC1 /dev/tty0 0 no
|
|
* SCC2 /dev/console 1 yes
|
|
* SCC3 /dev/tty1 2 no * USED FOR NETWORK I/F
|
|
* SCC4 /dev/tty2 3 no * USED FOR NETWORK I/F
|
|
*
|
|
* All ports support termios. The use of termios is recommended for real-time
|
|
* applications. Termios provides buffering and input processing. When not
|
|
* using termios, processing is limited to the substitution of LF for CR on
|
|
* input, and the output of a CR following the output of a LF character.
|
|
* Note that the terminal should not send CR/LF pairs when the return key
|
|
* is pressed, and that output lines are terminated with LF/CR, not CR/LF
|
|
* (although that would be easy to change).
|
|
*
|
|
* I/O may be interrupt-driven (recommended for real-time applications) or
|
|
* polled. Polled I/O may be performed by this device driver entirely, or
|
|
* in part by EPPCBug. With EPPCBug 1.1, polled I/O is limited to the
|
|
* EPPCBug debug console. This is a limitation of the firmware. Later
|
|
* firmware may be able to do I/O through any port. This code assumes
|
|
* that the EPPCBug console is the default: SMC1. If the console and
|
|
* printk ports are set to anything else with EPPCBug polled I/O, the
|
|
* system will hang. Only port SMC1 is usable with EPPCBug polled I/O.
|
|
*
|
|
* LIMITATIONS:
|
|
*
|
|
* It is not possible to use different I/O modes on the different ports. The
|
|
* exception is with printk. The printk port can use a different mode from
|
|
* the other ports. If this is done, it is important not to open the printk
|
|
* port from an RTEMS application.
|
|
*
|
|
* Currently, the I/O modes are determined at build time. It would be much
|
|
* better to have the mode selected at boot time based on parameters in
|
|
* NVRAM.
|
|
*
|
|
* Interrupt-driven I/O requires termios.
|
|
*
|
|
* TESTS:
|
|
*
|
|
* TO RUN THE TESTS, USE POLLED I/O WITHOUT TERMIOS SUPPORT. Some tests
|
|
* play with the interrupt masks and turn off I/O. Those tests will hang
|
|
* when interrupt-driven I/O is used. Other tests, such as cdtest, do I/O
|
|
* from the static constructors before the console is open. This test
|
|
* will not work with interrupt-driven I/O. Because of the buffering
|
|
* performed in termios, test output may not be in sequence.The tests
|
|
* should all be fixed to work with interrupt-driven I/O and to
|
|
* produce output in the expected sequence. Obviously, the termios test
|
|
* requires termios support in the driver.
|
|
*
|
|
* Set CONSOLE_MINOR to the appropriate device minor number in the
|
|
* config file. This allows the RTEMS application console to be different
|
|
* from the EPPBug debug console or the GDB port.
|
|
*
|
|
* This driver handles all five available serial ports: it distinguishes
|
|
* the sub-devices using minor device numbers. It is not possible to have
|
|
* other protocols running on the other ports when this driver is used as
|
|
* currently written.
|
|
*/
|
|
|
|
/*
|
|
* Based on code (alloc860.c in eth_comm port) by
|
|
* Jay Monkman (jmonkman@frasca.com),
|
|
* Copyright (C) 1998 by Frasca International, Inc.
|
|
*
|
|
* Modifications by Darlene Stewart <Darlene.Stewart@iit.nrc.ca>
|
|
* and Charles-Antoine Gauthier <charles.gauthier@iit.nrc.ca>.
|
|
* Copyright (c) 2000, National Research Council of Canada
|
|
*
|
|
* Modifications by Andy Dachs <iwe@fsmal.net> for MPC8260
|
|
* support.
|
|
*/
|
|
#include <stdarg.h>
|
|
#include <stdio.h>
|
|
#include <termios.h>
|
|
|
|
#include <rtems/console.h>
|
|
#include <rtems/bspIo.h>
|
|
#include <rtems/libio.h>
|
|
#include <bsp.h>
|
|
|
|
static void _BSP_output_char( char c );
|
|
static rtems_status_code do_poll_read( rtems_device_major_number major, rtems_device_minor_number minor, void * arg);
|
|
static rtems_status_code do_poll_write( rtems_device_major_number major, rtems_device_minor_number minor, void * arg);
|
|
|
|
BSP_output_char_function_type BSP_output_char = _BSP_output_char;
|
|
BSP_polling_getchar_function_type BSP_poll_char = NULL;
|
|
|
|
/*
|
|
* do_poll_read
|
|
*
|
|
* Input characters through polled I/O. Returns has soon as a character has
|
|
* been received. Otherwise, if we wait for the number of requested characters,
|
|
* we could be here forever!
|
|
*
|
|
* CR is converted to LF on input. The terminal should not send a CR/LF pair
|
|
* when the return or enter key is pressed.
|
|
*
|
|
* Input parameters:
|
|
* major - ignored. Should be the major number for this driver.
|
|
* minor - selected channel.
|
|
* arg->buffer - where to put the received characters.
|
|
* arg->count - number of characters to receive before returning--Ignored.
|
|
*
|
|
* Output parameters:
|
|
* arg->bytes_moved - the number of characters read. Always 1.
|
|
*
|
|
* Return value: RTEMS_SUCCESSFUL
|
|
*
|
|
* CANNOT BE COMBINED WITH INTERRUPT DRIVEN I/O!
|
|
*/
|
|
static rtems_status_code do_poll_read(
|
|
rtems_device_major_number major,
|
|
rtems_device_minor_number minor,
|
|
void * arg
|
|
)
|
|
{
|
|
(void) major;
|
|
|
|
rtems_libio_rw_args_t *rw_args = arg;
|
|
int c;
|
|
|
|
#define BSP_READ m8xx_uart_pollRead
|
|
|
|
while( (c = BSP_READ(minor)) == -1 );
|
|
rw_args->buffer[0] = (uint8_t)c;
|
|
if( rw_args->buffer[0] == '\r' )
|
|
rw_args->buffer[0] = '\n';
|
|
rw_args->bytes_moved = 1;
|
|
return RTEMS_SUCCESSFUL;
|
|
}
|
|
|
|
/*
|
|
* do_poll_write
|
|
*
|
|
* Output characters through polled I/O. Returns only once every character has
|
|
* been sent.
|
|
*
|
|
* CR is transmitted AFTER a LF on output.
|
|
*
|
|
* Input parameters:
|
|
* major - ignored. Should be the major number for this driver.
|
|
* minor - selected channel
|
|
* arg->buffer - where to get the characters to transmit.
|
|
* arg->count - the number of characters to transmit before returning.
|
|
*
|
|
* Output parameters:
|
|
* arg->bytes_moved - the number of characters read
|
|
*
|
|
* Return value: RTEMS_SUCCESSFUL
|
|
*
|
|
* CANNOT BE COMBINED WITH INTERRUPT DRIVEN I/O!
|
|
*/
|
|
static rtems_status_code do_poll_write(
|
|
rtems_device_major_number major,
|
|
rtems_device_minor_number minor,
|
|
void * arg
|
|
)
|
|
{
|
|
(void) major;
|
|
|
|
rtems_libio_rw_args_t *rw_args = arg;
|
|
uint32_t i;
|
|
char cr ='\r';
|
|
|
|
#define BSP_WRITE m8xx_uart_pollWrite
|
|
|
|
for( i = 0; i < rw_args->count; i++ ) {
|
|
BSP_WRITE(minor, &(rw_args->buffer[i]), 1);
|
|
if ( rw_args->buffer[i] == '\n' )
|
|
BSP_WRITE(minor, &cr, 1);
|
|
}
|
|
rw_args->bytes_moved = i;
|
|
return RTEMS_SUCCESSFUL;
|
|
|
|
}
|
|
|
|
/*
|
|
* Print functions prototyped in bspIo.h
|
|
*/
|
|
|
|
static void _BSP_output_char( char c )
|
|
{
|
|
/*
|
|
* Can't rely on console_initialize having been called before this function
|
|
* is used, so it may fail unless output is done through EPPC-Bug.
|
|
*/
|
|
#define PRINTK_WRITE m8xx_uart_pollWrite
|
|
|
|
PRINTK_WRITE( PRINTK_MINOR, &c, 1 );
|
|
}
|
|
|
|
/*
|
|
***************
|
|
* BOILERPLATE *
|
|
***************
|
|
*
|
|
* All these functions are prototyped in rtems/c/src/lib/include/console.h.
|
|
*/
|
|
|
|
/*
|
|
* Initialize and register the device
|
|
*/
|
|
rtems_device_driver console_initialize(
|
|
rtems_device_major_number major,
|
|
rtems_device_minor_number minor,
|
|
void *arg
|
|
)
|
|
{
|
|
(void) major;
|
|
(void) minor;
|
|
(void) arg;
|
|
|
|
rtems_status_code status;
|
|
rtems_device_minor_number console_minor;
|
|
|
|
/*
|
|
* Set up TERMIOS if needed
|
|
*/
|
|
|
|
console_minor = CONSOLE_MINOR;
|
|
|
|
#if UARTS_USE_TERMIOS == 1
|
|
|
|
rtems_termios_initialize ();
|
|
#else
|
|
rtems_termios_initialize ();
|
|
#endif /* UARTS_USE_TERMIOS */
|
|
|
|
/*
|
|
* Do common initialization.
|
|
*/
|
|
m8xx_uart_initialize();
|
|
|
|
/*
|
|
* Do device-specific initialization
|
|
*/
|
|
#if 0
|
|
m8xx_uart_smc_initialize(SMC1_MINOR); /* /dev/tty4 */
|
|
m8xx_uart_smc_initialize(SMC2_MINOR); /* /dev/tty5 */
|
|
#endif
|
|
|
|
m8xx_uart_scc_initialize(SCC1_MINOR); /* /dev/tty0 */
|
|
m8xx_uart_scc_initialize(SCC2_MINOR); /* /dev/tty1 */
|
|
|
|
#if 0 /* used as network connections */
|
|
m8xx_uart_scc_initialize(SCC3_MINOR); /* /dev/tty2 */
|
|
m8xx_uart_scc_initialize(SCC4_MINOR); /* /dev/tty3 */
|
|
#endif
|
|
|
|
/*
|
|
* Set up interrupts
|
|
*/
|
|
m8xx_uart_interrupts_initialize();
|
|
|
|
status = rtems_io_register_name ("/dev/tty0", major, SCC1_MINOR);
|
|
if (status != RTEMS_SUCCESSFUL)
|
|
rtems_fatal_error_occurred (status);
|
|
chmod("/dev/tty0",0660);
|
|
chown("/dev/tty0",2,0);
|
|
|
|
status = rtems_io_register_name ("/dev/tty1", major, SCC2_MINOR);
|
|
if (status != RTEMS_SUCCESSFUL)
|
|
rtems_fatal_error_occurred (status);
|
|
chmod("/dev/tty1",0660);
|
|
chown("/dev/tty1",2,0);
|
|
|
|
#if 0
|
|
status = rtems_io_register_name ("/dev/tty2", major, SCC3_MINOR);
|
|
if (status != RTEMS_SUCCESSFUL)
|
|
rtems_fatal_error_occurred (status);
|
|
|
|
status = rtems_io_register_name ("/dev/tty3", major, SCC4_MINOR);
|
|
if (status != RTEMS_SUCCESSFUL)
|
|
rtems_fatal_error_occurred (status);
|
|
|
|
status = rtems_io_register_name ("/dev/tty4", major, SMC1_MINOR);
|
|
if (status != RTEMS_SUCCESSFUL)
|
|
rtems_fatal_error_occurred (status);
|
|
|
|
status = rtems_io_register_name ("/dev/tty5", major, SMC2_MINOR);
|
|
if (status != RTEMS_SUCCESSFUL)
|
|
rtems_fatal_error_occurred (status);
|
|
#endif
|
|
/* Now register the RTEMS console */
|
|
status = rtems_io_register_name ("/dev/console", major, console_minor);
|
|
if (status != RTEMS_SUCCESSFUL)
|
|
rtems_fatal_error_occurred (status);
|
|
chmod("/dev/console",0666);
|
|
chown("/dev/console",2,0);
|
|
|
|
return RTEMS_SUCCESSFUL;
|
|
}
|
|
|
|
/*
|
|
* Open the device
|
|
*/
|
|
rtems_device_driver console_open(
|
|
rtems_device_major_number major,
|
|
rtems_device_minor_number minor,
|
|
void *arg
|
|
)
|
|
{
|
|
#if UARTS_IO_MODE == 1 /* RTEMS interrupt-driven I/O with termios */
|
|
/* Used to track termios private data for callbacks */
|
|
extern struct rtems_termios_tty *ttyp[];
|
|
rtems_libio_open_close_args_t *args = arg;
|
|
|
|
static const rtems_termios_callbacks intrCallbacks = {
|
|
NULL, /* firstOpen */
|
|
NULL, /* lastClose */
|
|
NULL, /* pollRead */
|
|
m8xx_uart_write, /* write */
|
|
m8xx_uart_setAttributes, /* setAttributes */
|
|
NULL, /* stopRemoteTx */
|
|
NULL, /* startRemoteTx */
|
|
TERMIOS_IRQ_DRIVEN /* outputUsesInterrupts */
|
|
};
|
|
#else
|
|
#if (UARTS_USE_TERMIOS == 1) && (UARTS_IO_MODE != 1)
|
|
static const rtems_termios_callbacks pollCallbacks = {
|
|
NULL, /* firstOpen */
|
|
NULL, /* lastClose */
|
|
m8xx_uart_pollRead, /* pollRead */
|
|
m8xx_uart_pollWrite, /* write */
|
|
m8xx_uart_setAttributes, /* setAttributes */
|
|
NULL, /* stopRemoteTx */
|
|
NULL, /* startRemoteTx */
|
|
TERMIOS_POLLED /* outputUsesInterrupts */
|
|
};
|
|
#endif
|
|
|
|
#endif
|
|
|
|
rtems_status_code sc;
|
|
|
|
if ( minor > NUM_PORTS-1 )
|
|
return RTEMS_INVALID_NUMBER;
|
|
|
|
#if UARTS_USE_TERMIOS == 1
|
|
|
|
#if UARTS_IO_MODE == 1 /* RTEMS interrupt-driven I/O with termios */
|
|
sc = rtems_termios_open( major, minor, arg, &intrCallbacks );
|
|
ttyp[minor] = args->iop->data1; /* Keep cookie returned by termios_open */
|
|
#else /* RTEMS polled I/O with termios */
|
|
sc = rtems_termios_open( major, minor, arg, &pollCallbacks );
|
|
#endif
|
|
|
|
#else /* UARTS_USE_TERMIOS != 1 */
|
|
(void) major;
|
|
(void) minor;
|
|
(void) arg;
|
|
|
|
/* no termios -- default to polled I/O */
|
|
sc = RTEMS_SUCCESSFUL;
|
|
#endif /* UARTS_USE_TERMIOS != 1 */
|
|
|
|
return sc;
|
|
|
|
}
|
|
|
|
/*
|
|
* Close the device
|
|
*/
|
|
rtems_device_driver console_close(
|
|
rtems_device_major_number major,
|
|
rtems_device_minor_number minor,
|
|
void *arg
|
|
)
|
|
{
|
|
(void) major;
|
|
(void) arg;
|
|
|
|
if ( minor > NUM_PORTS-1 )
|
|
return RTEMS_INVALID_NUMBER;
|
|
|
|
#if UARTS_USE_TERMIOS == 1
|
|
return rtems_termios_close( arg );
|
|
#else
|
|
return RTEMS_SUCCESSFUL;
|
|
#endif
|
|
|
|
}
|
|
|
|
/*
|
|
* Read from the device
|
|
*/
|
|
rtems_device_driver console_read(
|
|
rtems_device_major_number major,
|
|
rtems_device_minor_number minor,
|
|
void *arg
|
|
)
|
|
{
|
|
if ( minor > NUM_PORTS-1 )
|
|
return RTEMS_INVALID_NUMBER;
|
|
|
|
#if UARTS_USE_TERMIOS == 1
|
|
return rtems_termios_read( arg );
|
|
#else
|
|
return do_poll_read( major, minor, arg );
|
|
#endif
|
|
|
|
}
|
|
|
|
/*
|
|
* Write to the device
|
|
*/
|
|
rtems_device_driver console_write(
|
|
rtems_device_major_number major,
|
|
rtems_device_minor_number minor,
|
|
void *arg
|
|
)
|
|
{
|
|
if ( minor > NUM_PORTS-1 )
|
|
return RTEMS_INVALID_NUMBER;
|
|
|
|
#if UARTS_USE_TERMIOS == 1
|
|
return rtems_termios_write( arg );
|
|
#else
|
|
/* no termios -- default to polled */
|
|
return do_poll_write( major, minor, arg );
|
|
#endif
|
|
|
|
}
|
|
|
|
/*
|
|
* Handle ioctl request.
|
|
*/
|
|
rtems_device_driver console_control(
|
|
rtems_device_major_number major,
|
|
rtems_device_minor_number minor,
|
|
void *arg
|
|
)
|
|
{
|
|
(void) major;
|
|
(void) arg;
|
|
|
|
if ( minor > NUM_PORTS-1 )
|
|
return RTEMS_INVALID_NUMBER;
|
|
|
|
#if UARTS_USE_TERMIOS == 1
|
|
return rtems_termios_ioctl( arg );
|
|
#else
|
|
return RTEMS_SUCCESSFUL;
|
|
#endif
|
|
|
|
}
|
|
|
|
/*
|
|
* Support routine for console-generic
|
|
*/
|
|
int mbx8xx_console_get_configuration(void)
|
|
{
|
|
#if UARTS_IO_MODE == 1
|
|
return 0x02;
|
|
#else
|
|
return 0;
|
|
#endif
|
|
|
|
}
|