summaryrefslogtreecommitdiffstats
path: root/bsps/sh
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2018-04-19 06:28:01 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2018-04-20 13:08:32 +0200
commitd7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc (patch)
treecaa54b4229e86a68c84ab5961af34e087dce5302 /bsps/sh
parentbsps/powerpc: Move shared btimer support (diff)
downloadrtems-d7d66d7d4523b904c8ccc6aea3709dc0d5aa5bdc.tar.bz2
bsps: Move console drivers to bsps
This patch is a part of the BSP source reorganization. Update #3285.
Diffstat (limited to 'bsps/sh')
-rw-r--r--bsps/sh/gensh1/console/sci.c358
-rw-r--r--bsps/sh/gensh2/console/config.c130
-rw-r--r--bsps/sh/gensh2/console/sci.c554
-rw-r--r--bsps/sh/gensh2/console/sci_termios.c449
-rw-r--r--bsps/sh/gensh4/console/console.c469
-rw-r--r--bsps/sh/gensh4/console/sh4uart.c910
-rw-r--r--bsps/sh/shsim/console/console-debugio.c33
-rw-r--r--bsps/sh/shsim/console/console-io.c57
-rw-r--r--bsps/sh/shsim/console/console-support.S18
9 files changed, 2978 insertions, 0 deletions
diff --git a/bsps/sh/gensh1/console/sci.c b/bsps/sh/gensh1/console/sci.c
new file mode 100644
index 0000000000..04d9ca5c70
--- /dev/null
+++ b/bsps/sh/gensh1/console/sci.c
@@ -0,0 +1,358 @@
+/*
+ * /dev/sci[0|1] for Hitachi SH 703X
+ *
+ * Author: Ralf Corsepius (corsepiu@faw.uni-ulm.de)
+ *
+ * COPYRIGHT (c) 1997-1999, Ralf Corsepius, Ulm, Germany
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ *
+ * COPYRIGHT (c) 1998.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <rtems.h>
+
+#include <stdlib.h>
+
+#include <rtems/libio.h>
+#include <rtems/iosupp.h>
+#include <rtems/score/sh_io.h>
+#include <rtems/score/ispsh7032.h>
+#include <rtems/score/iosh7032.h>
+#include <sh/sh7_sci.h>
+#include <sh/sh7_pfc.h>
+#include <sh/sci.h>
+
+/*
+ * NOTE: Some SH variants have 3 sci devices
+ */
+
+#define SCI_MINOR_DEVICES 2
+
+#define SH_SCI_BASE_0 SCI0_SMR
+#define SH_SCI_BASE_1 SCI1_SMR
+
+struct scidev_t {
+ char * name ;
+ uint32_t addr ;
+ rtems_device_minor_number minor ;
+ unsigned short opened ;
+ tcflag_t cflags ;
+ speed_t spd ;
+} sci_device[SCI_MINOR_DEVICES] =
+{
+ { "/dev/sci0", SH_SCI_BASE_0, 0, 0, CS8, B9600 },
+ { "/dev/sci1", SH_SCI_BASE_1, 1, 0, CS8, B9600 }
+} ;
+
+/* imported from scitab.rel */
+extern int _sci_get_brparms(
+ speed_t spd,
+ unsigned char *smr,
+ unsigned char *brr );
+
+/* Translate termios' tcflag_t into sci settings */
+static int _sci_set_cflags(
+ struct scidev_t *sci_dev,
+ tcflag_t c_cflag,
+ speed_t spd )
+{
+ uint8_t smr ;
+ uint8_t brr ;
+
+ if ( spd )
+ {
+ if ( _sci_get_brparms( spd, &smr, &brr ) != 0 )
+ return -1 ;
+ }
+
+ if ( c_cflag & CSIZE )
+ {
+ if ( c_cflag & CS8 )
+ smr &= ~SCI_SEVEN_BIT_DATA;
+ else if ( c_cflag & CS7 )
+ smr |= SCI_SEVEN_BIT_DATA;
+ else
+ return -1 ;
+ }
+
+ if ( c_cflag & CSTOPB )
+ smr |= SCI_STOP_BITS_2;
+ else
+ smr &= ~SCI_STOP_BITS_2;
+
+ if ( c_cflag & PARENB )
+ smr |= SCI_PARITY_ON ;
+ else
+ smr &= ~SCI_PARITY_ON ;
+
+ if ( c_cflag & PARODD )
+ smr |= SCI_ODD_PARITY ;
+ else
+ smr &= ~SCI_ODD_PARITY;
+
+ write8( smr, sci_dev->addr + SCI_SMR );
+ write8( brr, sci_dev->addr + SCI_BRR );
+
+ return 0 ;
+}
+
+static void _sci_init(
+ rtems_device_minor_number minor )
+{
+ uint16_t temp16 ;
+
+ /* Pin function controller initialisation for asynchronous mode */
+ if( minor == 0)
+ {
+ temp16 = read16( PFC_PBCR1);
+ temp16 &= ~( PB8MD | PB9MD );
+ temp16 |= (PB_TXD0 | PB_RXD0);
+ write16( temp16, PFC_PBCR1);
+ }
+ else
+ {
+ temp16 = read16( PFC_PBCR1);
+ temp16 &= ~( PB10MD | PB11MD);
+ temp16 |= (PB_TXD1 | PB_RXD1);
+ write16( temp16, PFC_PBCR1);
+ }
+
+ /* disable sck-pin */
+ if( minor == 0)
+ {
+ temp16 = read16( PFC_PBCR1);
+ temp16 &= ~(PB12MD);
+ write16( temp16, PFC_PBCR1);
+ }
+ else
+ {
+ temp16 = read16( PFC_PBCR1);
+ temp16 &= ~(PB13MD);
+ write16( temp16, PFC_PBCR1);
+ }
+}
+
+static void _sci_tx_polled(
+ int minor,
+ const char buf )
+{
+ struct scidev_t *scidev = &sci_device[minor] ;
+ int8_t ssr ;
+
+ while ( !inb((scidev->addr + SCI_SSR) & SCI_TDRE ))
+ ;
+ write8(buf,scidev->addr+SCI_TDR);
+
+ ssr = inb(scidev->addr+SCI_SSR);
+ ssr &= ~SCI_TDRE ;
+ write8(ssr,scidev->addr+SCI_SSR);
+}
+
+static int _sci_rx_polled (
+ int minor)
+{
+ struct scidev_t *scidev = &sci_device[minor] ;
+
+ unsigned char c;
+ char ssr ;
+ ssr = read8(scidev->addr + SCI_SSR) ;
+
+ if (ssr & (SCI_PER | SCI_FER | SCI_ORER))
+ write8(ssr & ~(SCI_PER | SCI_FER | SCI_ORER), scidev->addr+SCI_SSR);
+
+ if ( !(ssr & SCI_RDRF) )
+ return -1;
+
+ c = read8(scidev->addr + SCI_RDR) ;
+
+ write8(ssr & ~SCI_RDRF,scidev->addr + SCI_SSR);
+ return c;
+}
+
+/*
+ * sci_initialize
+ */
+
+rtems_device_driver sh_sci_initialize(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg )
+{
+ rtems_device_driver status ;
+ rtems_device_minor_number i;
+
+ /*
+ * register all possible devices.
+ * the initialization of the hardware is done by sci_open
+ */
+
+ for ( i = 0 ; i < SCI_MINOR_DEVICES ; i++ )
+ {
+ status = rtems_io_register_name(
+ sci_device[i].name,
+ major,
+ sci_device[i].minor );
+ if (status != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred(status);
+ }
+
+ /* default hardware setup */
+
+ return RTEMS_SUCCESSFUL;
+}
+
+
+/*
+ * Open entry point
+ */
+
+rtems_device_driver sh_sci_open(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg )
+{
+ uint8_t temp8;
+
+ /* check for valid minor number */
+ if(( minor > ( SCI_MINOR_DEVICES -1 )) || ( minor < 0 ))
+ {
+ return RTEMS_INVALID_NUMBER;
+ }
+
+ /* device already opened */
+ if ( sci_device[minor].opened > 0 )
+ {
+ sci_device[minor].opened++ ;
+ return RTEMS_SUCCESSFUL ;
+ }
+
+ _sci_init( minor );
+
+ if (minor == 0) {
+ temp8 = read8(sci_device[minor].addr + SCI_SCR);
+ temp8 &= ~(SCI_TE | SCI_RE) ;
+ write8(temp8, sci_device[minor].addr + SCI_SCR); /* Clear SCR */
+ _sci_set_cflags( &sci_device[minor], sci_device[minor].cflags, sci_device[minor].spd );
+
+/* FIXME: Should be one bit delay */
+ CPU_delay(50000); /* microseconds */
+
+ temp8 |= SCI_RE | SCI_TE;
+ write8(temp8, sci_device[minor].addr + SCI_SCR); /* Enable clock output */
+ } else {
+ temp8 = read8(sci_device[minor].addr + SCI_SCR);
+ temp8 &= ~(SCI_TE | SCI_RE) ;
+ write8(temp8, sci_device[minor].addr + SCI_SCR); /* Clear SCR */
+ _sci_set_cflags( &sci_device[minor], sci_device[minor].cflags, sci_device[minor].spd );
+
+/* FIXME: Should be one bit delay */
+ CPU_delay(50000); /* microseconds */
+
+ temp8 |= SCI_RE | SCI_TE;
+ write8(temp8, sci_device[minor].addr + SCI_SCR); /* Enable clock output */
+ }
+
+ sci_device[minor].opened++ ;
+
+ return RTEMS_SUCCESSFUL ;
+}
+
+/*
+ * Close entry point
+ */
+
+rtems_device_driver sh_sci_close(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+)
+{
+ if( sci_device[minor].opened == 0 )
+ {
+ return RTEMS_INVALID_NUMBER;
+ }
+
+ sci_device[minor].opened-- ;
+
+ return RTEMS_SUCCESSFUL ;
+}
+
+/*
+ * read bytes from the serial port.
+ */
+
+rtems_device_driver sh_sci_read(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+)
+{
+ int count = 0;
+
+ rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *) arg;
+ char * buffer = rw_args->buffer;
+ int maximum = rw_args->count;
+
+ for (count = 0; count < maximum; count++) {
+ buffer[ count ] = _sci_rx_polled(minor);
+ if (buffer[ count ] == '\n' || buffer[ count ] == '\r') {
+ buffer[ count++ ] = '\n';
+ break;
+ }
+ }
+
+ rw_args->bytes_moved = count;
+ return (count >= 0) ? RTEMS_SUCCESSFUL : RTEMS_UNSATISFIED;
+}
+
+/*
+ * write bytes to the serial port.
+ */
+
+rtems_device_driver sh_sci_write(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+)
+{
+ int count;
+
+ rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *) arg;
+ char *buffer = rw_args->buffer;
+ int maximum = rw_args->count;
+
+ for (count = 0; count < maximum; count++) {
+#if 0
+ if ( buffer[ count ] == '\n') {
+ outbyte(minor, '\r');
+ }
+#endif
+ _sci_tx_polled( minor, buffer[ count ] );
+ }
+
+ rw_args->bytes_moved = maximum;
+ return 0;
+}
+
+/*
+ * IO Control entry point
+ */
+
+rtems_device_driver sh_sci_control(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+)
+{
+ /* Not yet supported */
+ return RTEMS_SUCCESSFUL ;
+}
diff --git a/bsps/sh/gensh2/console/config.c b/bsps/sh/gensh2/console/config.c
new file mode 100644
index 0000000000..a2f25742dd
--- /dev/null
+++ b/bsps/sh/gensh2/console/config.c
@@ -0,0 +1,130 @@
+/*
+ * This file contains the TTY driver table. The implementation is
+ * based on libchip/serial drivers, but it uses internal SHx SCI so
+ * the implementation of the driver is placed in
+ * lib/libcpu/sh/sh7045/sci instead of libchip/serial.
+ *
+ * COPYRIGHT (c) 1989-2001.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ *
+ */
+
+#include <bsp.h>
+#include <libchip/serial.h>
+#include <libchip/sersupp.h>
+#include <sh/sci_termios.h>
+#include <rtems/score/sh_io.h>
+#include <rtems/score/ispsh7045.h>
+#include <rtems/score/iosh7045.h>
+#include <rtems/termiostypes.h>
+
+/*
+ * Function set for interrupt enabled termios console
+ */
+const console_fns sh_sci_fns =
+{
+ libchip_serial_default_probe, /* deviceProbe */
+ sh_sci_first_open, /* deviceFirstOpen */
+ NULL, /* deviceLastClose */
+ NULL, /* deviceRead */
+ sh_sci_write_support_int, /* deviceWrite */
+ sh_sci_initialize_interrupts, /* deviceInitialize */
+ sh_sci_write_polled, /* deviceWritePolled */
+ sh_sci_set_attributes, /* deviceSetAttributes */
+ TERMIOS_IRQ_DRIVEN /* deviceOutputUsesInterrupts */
+};
+
+/*
+ * Function set for polled termios console
+ */
+const console_fns sh_sci_fns_polled =
+{
+ libchip_serial_default_probe, /* deviceProbe */
+ sh_sci_first_open, /* deviceFirstOpen */
+ sh_sci_last_close, /* deviceLastClose */
+ sh_sci_inbyte_nonblocking_polled, /* deviceRead */
+ sh_sci_write_support_polled, /* deviceWrite */
+ sh_sci_init, /* deviceInitialize */
+ sh_sci_write_polled, /* deviceWritePolled */
+ sh_sci_set_attributes, /* deviceSetAttributes */
+ TERMIOS_POLLED /* deviceOutputUsesInterrupts */
+};
+
+#if 1 /* (CONSOLE_USE_INTERRUPTS) */
+#define SCI_FUNCTIONS &sh_sci_fns
+#else
+#define SCI_FUNCTIONS &sh_sci_fns_polled
+#endif
+
+static const struct termios term1 = {
+ 0,
+ 0,
+ 0,
+ 0,
+ {0},
+ B9600 | CS8,
+ B9600 | CS8
+};
+
+static const struct termios term2 = {
+ 0,
+ 0,
+ 0,
+ 0,
+ {0},
+ B115200 | CS8,
+ B115200 | CS8
+};
+
+console_tbl Console_Configuration_Ports[] = {
+ {
+ "/dev/sci0", /* sDeviceName */
+ SERIAL_CUSTOM, /* deviceType */
+ SCI_FUNCTIONS, /* pDeviceFns */
+ NULL, /* deviceProbe */
+ NULL, /* pDeviceFlow */
+ 16, /* ulMargin */
+ 8, /* ulHysteresis */
+ (void *)&term1, /* baud rate */ /* pDeviceParams */
+ SCI_SMR0, /* ulCtrlPort1 */
+ 3, /* ulCtrlPort2 as IRQ priority level*/
+ TXI0_ISP_V, /* ulDataPort as TX end vector number*/
+ NULL, /* unused */ /* getRegister */
+ NULL, /* unused */ /* setRegister */
+ NULL, /* unused */ /* getData */
+ NULL, /* unused */ /* setData */
+ 0, /* ulClock */
+ RXI0_ISP_V, /* ulIntVector as RX end vector number*/
+ },
+ {
+ "/dev/sci1", /* sDeviceName */
+ SERIAL_CUSTOM, /* deviceType */
+ SCI_FUNCTIONS, /* pDeviceFns */
+ NULL, /* deviceProbe */
+ NULL, /* pDeviceFlow */
+ 16, /* ulMargin */
+ 8, /* ulHysteresis */
+ (void *)&term2, /* baud rate */ /* pDeviceParams */
+ SCI_SMR1, /* ulCtrlPort1 */
+ 3, /* ulCtrlPort2 as IRQ priority level*/
+ TXI1_ISP_V, /* ulDataPort as TX end vector number*/
+ NULL, /* unused */ /* getRegister */
+ NULL, /* unused */ /* setRegister */
+ NULL, /* unused */ /* getData */
+ NULL, /* unused */ /* setData */
+ 0, /* ulClock */
+ RXI1_ISP_V, /* ulIntVector as RX end vector number*/
+ }
+};
+
+/*
+ * Declare some information used by the console driver
+ */
+
+#define NUM_CONSOLE_PORTS (sizeof(Console_Configuration_Ports)/sizeof(console_tbl))
+
+unsigned long Console_Configuration_Count = NUM_CONSOLE_PORTS;
diff --git a/bsps/sh/gensh2/console/sci.c b/bsps/sh/gensh2/console/sci.c
new file mode 100644
index 0000000000..143fc1bb94
--- /dev/null
+++ b/bsps/sh/gensh2/console/sci.c
@@ -0,0 +1,554 @@
+/*
+ * /dev/sci[0|1] for Hitachi SH 704X
+ *
+ * The SH doesn't have a designated console device. Therefore we "alias"
+ * another device as /dev/console and revector all calls to /dev/console
+ * to this device.
+ *
+ * This approach is similar to installing a sym-link from one device to
+ * another device. If rtems once will support sym-links for devices files,
+ * this implementation could be dropped.
+ */
+
+/*
+ * Author: Ralf Corsepius (corsepiu@faw.uni-ulm.de)
+ *
+ * COPYRIGHT (c) 1997-1998, FAW Ulm, Germany
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ *
+ * COPYRIGHT (c) 1998.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ *
+ * Modified to reflect sh7045 processor:
+ * John M. Mills (jmills@tga.com)
+ * TGA Technologies, Inc.
+ * 100 Pinnacle Way, Suite 140
+ * Norcross, GA 30071 U.S.A.
+ *
+ * This modified file may be copied and distributed in accordance
+ * the above-referenced license. It is provided for critique and
+ * developmental purposes without any warranty nor representation
+ * by the authors or by TGA Technologies.
+ */
+
+#include <bsp.h>
+
+
+#include <stdlib.h>
+
+#include <rtems/libio.h>
+#include <rtems/iosupp.h>
+#include <rtems/score/sh_io.h>
+#include <rtems/score/ispsh7045.h>
+#include <rtems/score/iosh7045.h>
+#include <sh/sh7_sci.h>
+#include <sh/sh7_pfc.h>
+
+#include <sh/sci.h>
+
+#ifndef STANDALONE_EVB
+#define STANDALONE_EVB 0
+#endif
+
+/*
+ * NOTE: Some SH variants have 3 sci devices
+ */
+
+#define SCI_MINOR_DEVICES 2
+
+/*
+ * FIXME: sh7045 register names match Hitachi data book,
+ * but conflict with RTEMS sh7032 usage.
+ */
+
+#define SH_SCI_BASE_0 SCI_SMR0
+#define SH_SCI_BASE_1 SCI_SMR1
+
+#define SH_SCI_DEF_COMM_0 CS8, B9600
+#define SH_SCI_DEF_COMM_1 CS8, B38400
+/* #define SH_SCI_DEF_COMM_1 CS8, B9600 */
+
+struct scidev_t {
+ char * name;
+ uint32_t addr;
+ rtems_device_minor_number minor;
+ unsigned short opened;
+ tcflag_t cflags;
+ speed_t spd;
+} sci_device[SCI_MINOR_DEVICES] =
+{
+ { "/dev/sci0", SH_SCI_BASE_0, 0, 0, SH_SCI_DEF_COMM_0 },
+ { "/dev/sci1", SH_SCI_BASE_1, 1, 0, SH_SCI_DEF_COMM_1 }
+};
+
+/* local data structures maintain hardware configuration */
+#if UNUSED
+static sci_setup_t sio_param[2];
+#endif
+
+/* Translate termios' tcflag_t into sci settings */
+static int _sci_set_cflags(
+ struct scidev_t *sci_dev,
+ tcflag_t c_cflag,
+ speed_t spd
+)
+{
+ uint8_t smr;
+ uint8_t brr;
+
+ if ( spd )
+ {
+ if ( _sci_get_brparms( spd, &smr, &brr ) != 0 )
+ return -1;
+ }
+
+ if ( c_cflag & CSIZE )
+ {
+ if ( c_cflag & CS8 )
+ smr &= ~SCI_SEVEN_BIT_DATA;
+ else if ( c_cflag & CS7 )
+ smr |= SCI_SEVEN_BIT_DATA;
+ else
+ return -1;
+ }
+
+ if ( c_cflag & CSTOPB )
+ smr |= SCI_STOP_BITS_2;
+ else
+ smr &= ~SCI_STOP_BITS_2;
+
+ if ( c_cflag & PARENB )
+ smr |= SCI_PARITY_ON;
+ else
+ smr &= ~SCI_PARITY_ON;
+
+ if ( c_cflag & PARODD )
+ smr |= SCI_ODD_PARITY;
+ else
+ smr &= ~SCI_ODD_PARITY;
+
+ write8( smr, sci_dev->addr + SCI_SMR );
+ write8( brr, sci_dev->addr + SCI_BRR );
+
+ return 0;
+}
+
+/*
+ * local functions operate SCI ports 0 and 1
+ * called from polling routines or ISRs
+ */
+static bool wrtSCI0(unsigned char ch)
+{
+ uint8_t temp;
+ bool result = false;
+
+ if ((read8(SCI_SSR0) & SCI_TDRE) != 0x00) {
+ /* Write the character to the TDR */
+ write8(ch, SCI_TDR0);
+ /* Clear the TDRE bit */
+ temp = read8(SCI_SSR0) & ~SCI_TDRE;
+ write8(temp, SCI_SSR0);
+ result = true;
+ }
+ return result;
+} /* wrtSCI0 */
+
+static bool wrtSCI1(unsigned char ch)
+{
+ uint8_t temp;
+ bool result = false;
+
+ if ((read8(SCI_SSR1) & SCI_TDRE) != 0x00) {
+ /* Write the character to the TDR */
+ write8(ch, SCI_TDR1);
+ /* Clear the TDRE bit */
+ temp = read8(SCI_SSR1) & ~SCI_TDRE;
+ write8(temp, SCI_SSR1);
+ result = true;
+ }
+ return result;
+} /* wrtSCI1 */
+
+/* polled output steers byte to selected port */
+static void sh_sci_outbyte_polled(
+ rtems_device_minor_number minor,
+ char ch )
+{
+ if (minor == 0) /* blocks until port ready */
+ while (wrtSCI0(ch) != true); /* SCI0*/
+ else
+ while (wrtSCI1(ch) != true); /* SCI1*/
+} /* sh_sci_outbyte_polled */
+
+/*
+ * Initial version calls polled output driver and blocks
+ */
+static void outbyte(
+ rtems_device_minor_number minor,
+ char ch)
+{
+ sh_sci_outbyte_polled(minor, (unsigned char)ch);
+} /* outbyte */
+
+static bool rdSCI0(unsigned char *ch)
+{
+ uint8_t temp;
+ bool result = false;
+
+ if ((read8(SCI_SSR0) & SCI_RDRF) != 0x00) {
+ /* read input */
+ *ch = read8(SCI_RDR0);
+ /* Clear RDRF flag */
+ temp = read8(SCI_SSR0) & ~SCI_RDRF;
+ write8(temp, SCI_SSR0);
+ /* Check for transmission errors */
+ if (temp & (SCI_ORER | SCI_FER | SCI_PER)) {
+ /* TODO: report to RTEMS transmission error */
+
+ /* clear error flags*/
+ temp &= ~(SCI_ORER | SCI_FER | SCI_PER);
+ write8(temp, SCI_SSR0);
+ }
+ result = true;
+ }
+ return result;
+} /* rdSCI0 */
+
+static bool rdSCI1(unsigned char *ch)
+{
+ uint8_t temp;
+ bool result = false;
+
+ if ((read8(SCI_SSR1) & SCI_RDRF) != 0x00) {
+ /* read input */
+ *ch = read8(SCI_RDR1);
+ /* Clear RDRF flag */
+ temp= read8(SCI_SSR1) & ~SCI_RDRF;
+ write8(temp, SCI_SSR1);
+ /* Check for transmission errors */
+ if (temp & (SCI_ORER | SCI_FER | SCI_PER)) {
+ /* TODO: report to RTEMS transmission error */
+
+ /* clear error flags*/
+ temp &= ~(SCI_ORER | SCI_FER | SCI_PER);
+ write8(temp, SCI_SSR1);
+ }
+ result = true;
+ }
+ return result;
+} /* rdSCI1 */
+
+/* initial version pulls byte from selected port */
+static char sh_sci_inbyte_polled( rtems_device_minor_number minor )
+{
+ uint8_t ch = 0;
+
+ if (minor == 0) /* blocks until char.ready */
+ while (rdSCI0(&ch) != true); /* SCI0 */
+ else
+ while (rdSCI1(&ch) != true); /* SCI1 */
+ return ch;
+} /* sh_sci_inbyte_polled */
+
+/* Initial version calls polled input driver */
+static char inbyte( rtems_device_minor_number minor )
+{
+ char ch;
+
+ ch = sh_sci_inbyte_polled(minor);
+ return ch;
+} /* inbyte */
+
+/* sh_sci_initialize
+ *
+ * This routine initializes (registers) the sh_sci IO drivers.
+ *
+ * Input parameters: ignored
+ *
+ * Output parameters: NONE
+ *
+ * Return values: RTEMS_SUCCESSFUL
+ * if all sci[...] register, else calls
+ * rtems_fatal_error_occurred(status)
+ */
+rtems_device_driver sh_sci_initialize(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg )
+{
+ rtems_device_driver status;
+ rtems_device_minor_number i;
+
+ /*
+ * register all possible devices.
+ * the initialization of the hardware is done by sci_open
+ *
+ * One of devices could be previously registered by console
+ * initialization therefore we check it everytime
+ */
+ for ( i = 0 ; i < SCI_MINOR_DEVICES ; i++ ) {
+ /* OK. We assume it is not registered yet. */
+ status = rtems_io_register_name(
+ sci_device[i].name,
+ major,
+ sci_device[i].minor
+ );
+ if (status != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred(status);
+ }
+
+ /* non-default hardware setup occurs in sh_sci_open() */
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * Open entry point
+ * Sets up port and pins for selected sci.
+ */
+rtems_device_driver sh_sci_open(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg )
+{
+ uint8_t temp8;
+ uint16_t temp16;
+
+ unsigned a;
+
+ /* check for valid minor number */
+ if (( minor > ( SCI_MINOR_DEVICES -1 )) || ( minor < 0 )) {
+ return RTEMS_INVALID_NUMBER;
+ }
+
+ /* device already opened */
+ if ( sci_device[minor].opened > 0 ) {
+ sci_device[minor].opened++;
+ return RTEMS_SUCCESSFUL;
+ }
+
+ /* set PFC registers to enable I/O pins */
+
+ if ((minor == 0)) {
+ temp16 = read16(PFC_PACRL2); /* disable SCK0, DMA, IRQ */
+ temp16 &= ~(PA2MD1 | PA2MD0);
+ temp16 |= (PA_TXD0 | PA_RXD0); /* enable pins for Tx0, Rx0 */
+ write16(temp16, PFC_PACRL2);
+
+ } else if (minor == 1) {
+ temp16 = read16(PFC_PACRL2); /* disable SCK1, DMA, IRQ */
+ temp16 &= ~(PA5MD1 | PA5MD0);
+ temp16 |= (PA_TXD1 | PA_RXD1); /* enable pins for Tx1, Rx1 */
+ write16(temp16, PFC_PACRL2);
+
+ } /* add other devices and pins as req'd. */
+
+ /* set up SCI registers */
+ write8(0x00, sci_device[minor].addr + SCI_SCR); /* Clear SCR */
+ /* set SMR and BRR */
+ _sci_set_cflags( &sci_device[minor], sci_device[minor].cflags, sci_device[minor].spd );
+
+ for (a=0; a < 10000L; a++) { /* Delay */
+ __asm__ volatile ("nop");
+ }
+
+ write8((SCI_RE | SCI_TE), /* enable async. Tx and Rx */
+ sci_device[minor].addr + SCI_SCR);
+
+ /* clear error flags */
+ temp8 = read8(sci_device[minor].addr + SCI_SSR);
+ while (temp8 & (SCI_RDRF | SCI_ORER | SCI_FER | SCI_PER)) {
+ temp8 = read8(sci_device[minor].addr + SCI_RDR); /* flush input */
+ temp8 = read8(sci_device[minor].addr + SCI_SSR); /* clear some flags */
+ write8(temp8 & ~(SCI_RDRF | SCI_ORER | SCI_FER | SCI_PER),
+ sci_device[minor].addr + SCI_SSR);
+ temp8 = read8(sci_device[minor].addr + SCI_SSR); /* check if everything is OK */
+ }
+ /* Clear RDRF flag */
+ write8(0x00, sci_device[minor].addr + SCI_TDR); /* force output */
+ /* Clear the TDRE bit */
+ temp8 = read8(sci_device[minor].addr + SCI_SSR) & ~SCI_TDRE;
+ write8(temp8, sci_device[minor].addr + SCI_SSR);
+
+ /* add interrupt setup if required */
+
+
+ sci_device[minor].opened++;
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * Close entry point
+ */
+rtems_device_driver sh_sci_close(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+)
+{
+ /* FIXME: Incomplete */
+ if ( sci_device[minor].opened > 0 )
+ sci_device[minor].opened--;
+ else
+ return RTEMS_INVALID_NUMBER;
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * read bytes from the serial port. We only have stdin.
+ */
+rtems_device_driver sh_sci_read(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+)
+{
+ rtems_libio_rw_args_t *rw_args;
+ char *buffer;
+ int maximum;
+ int count = 0;
+
+ rw_args = (rtems_libio_rw_args_t *) arg;
+
+ buffer = rw_args->buffer;
+ maximum = rw_args->count;
+
+ for (count = 0; count < maximum; count++) {
+ buffer[ count ] = inbyte(minor);
+ if (buffer[ count ] == '\n' || buffer[ count ] == '\r') {
+ buffer[ count++ ] = '\n';
+ break;
+ }
+ }
+
+ rw_args->bytes_moved = count;
+ return (count >= 0) ? RTEMS_SUCCESSFUL : RTEMS_UNSATISFIED;
+}
+
+/*
+ * write bytes to the serial port. Stdout and stderr are the same.
+ */
+rtems_device_driver sh_sci_write(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+)
+{
+ int count;
+ int maximum;
+ rtems_libio_rw_args_t *rw_args;
+ char *buffer;
+
+ rw_args = (rtems_libio_rw_args_t *) arg;
+
+ buffer = rw_args->buffer;
+ maximum = rw_args->count;
+
+ for (count = 0; count < maximum; count++) {
+ if ( buffer[ count ] == '\n') {
+ outbyte(minor, '\r');
+ }
+ outbyte( minor, buffer[ count ] );
+ }
+
+ rw_args->bytes_moved = maximum;
+ return 0;
+}
+
+/*
+ * IO Control entry point
+ */
+rtems_device_driver sh_sci_control(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg
+)
+{
+ /* Not yet supported */
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * Termios polled first open
+ */
+static int _sh_sci_poll_first_open(int major, int minor, void *arg)
+{
+ return sh_sci_open(major, minor, arg);
+}
+
+/*
+ * Termios general last close
+ */
+static int _sh_sci_last_close(int major, int minor, void *arg)
+{
+ return sh_sci_close(major, minor, arg);
+}
+
+/*
+ * Termios polled read
+ */
+static int _sh_sci_poll_read(int minor)
+{
+ int value = -1;
+ uint8_t ch = 0;
+
+ if ( minor == 0 ) {
+ if ( rdSCI0( &ch ) )
+ value = (int) ch;
+ } else if ( minor == 1 ) {
+ if ( rdSCI1( &ch ) )
+ value = (int) ch;
+ }
+ return value;
+}
+
+/*
+ * Termios polled write
+ */
+static ssize_t _sh_sci_poll_write(int minor, const char *buf, size_t len)
+{
+ size_t count;
+
+ for (count = 0; count < len; count++)
+ outbyte( minor, buf[count] );
+ return count;
+}
+
+/*
+ * Termios set attributes
+ */
+static int _sh_sci_set_attributes( int minor, const struct termios *t)
+{
+ return _sci_set_cflags( &sci_device[ minor ], t->c_cflag, t->c_ospeed);
+}
+
+
+const rtems_termios_callbacks sci_poll_callbacks = {
+ _sh_sci_poll_first_open, /* FirstOpen*/
+ _sh_sci_last_close, /* LastClose*/
+ _sh_sci_poll_read, /* PollRead */
+ _sh_sci_poll_write, /* Write */
+ _sh_sci_set_attributes, /* setAttributes */
+ NULL, /* stopRemoteTX */
+ NULL, /* StartRemoteTX */
+ 0 /* outputUsesInterrupts */
+};
+
+/* FIXME: not yet supported */
+const rtems_termios_callbacks sci_interrupt_callbacks;
+
+const rtems_termios_callbacks* sh_sci_get_termios_handlers( bool poll )
+{
+ return poll ?
+ &sci_poll_callbacks :
+ &sci_interrupt_callbacks;
+}
diff --git a/bsps/sh/gensh2/console/sci_termios.c b/bsps/sh/gensh2/console/sci_termios.c
new file mode 100644
index 0000000000..5d588065af
--- /dev/null
+++ b/bsps/sh/gensh2/console/sci_termios.c
@@ -0,0 +1,449 @@
+/*
+ * Termios console serial driver.
+ */
+
+/*
+ * Based on SCI driver by Ralf Corsepius and John M. Mills
+ *
+ * Author: Radzislaw Galler <rgaller@et.put.poznan.pl>
+ *
+ * COPYRIGHT (c) 1989-2001.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ *
+ */
+
+#include <bsp.h>
+#include <stdlib.h>
+
+#include <libchip/serial.h>
+#include <libchip/sersupp.h>
+
+#include <rtems/libio.h>
+#include <rtems/iosupp.h>
+
+#include <rtems/score/sh_io.h>
+#include <rtems/score/ispsh7045.h>
+#include <rtems/score/iosh7045.h>
+
+#include <sh/sh7_sci.h>
+#include <sh/sh7_pfc.h>
+#include <sh/sci_termios.h>
+
+
+/*
+ * Some handy macros
+ */
+#define SH_SCI_REG_DATA(_data, _minor, _register) \
+ (write8(_data, Console_Port_Tbl[_minor]->ulCtrlPort1 + (_register)))
+
+#define SH_SCI_REG_FLAG(_flag, _minor, _register) \
+ (write8(read8(Console_Port_Tbl[_minor]->ulCtrlPort1 + (_register)) | (_flag), \
+ Console_Port_Tbl[_minor]->ulCtrlPort1 + (_register)))
+
+#define SH_SCI_REG_MASK(_flag, _minor, _register) \
+ (write8(read8(Console_Port_Tbl[_minor]->ulCtrlPort1 + (_register)) & ~(_flag),\
+ Console_Port_Tbl[_minor]->ulCtrlPort1 + (_register)))
+
+/*
+ * NOTE: Some SH variants have 3 sci devices
+ */
+
+#define SCI_MINOR_DEVICES 2
+
+
+/*
+ * Automatically generated function imported from scitab.rel
+ */
+extern int _sci_get_brparms(
+ speed_t spd,
+ unsigned char *smr,
+ unsigned char *brr
+);
+
+/*
+ * Translate termios flags into SCI settings
+ */
+int sh_sci_set_attributes(
+ int minor,
+ const struct termios *t
+)
+{
+ uint8_t smr;
+ uint8_t brr;
+ int a;
+
+ tcflag_t c_cflag = t->c_cflag;
+ speed_t spd = t->c_ospeed;
+
+ if ( spd ) {
+ if ( _sci_get_brparms( spd, &smr, &brr ) != 0 )
+ return -1 ;
+ }
+
+ if ( c_cflag & CSIZE ) {
+ if ( c_cflag & CS8 )
+ smr &= ~SCI_SEVEN_BIT_DATA;
+ else if ( c_cflag & CS7 )
+ smr |= SCI_SEVEN_BIT_DATA;
+ else
+ return -1 ;
+ }
+
+ if ( c_cflag & CSTOPB )
+ smr |= SCI_STOP_BITS_2;
+ else
+ smr &= ~SCI_STOP_BITS_2;
+
+ if ( c_cflag & PARENB )
+ smr |= SCI_PARITY_ON ;
+ else
+ smr &= ~SCI_PARITY_ON ;
+
+ if ( c_cflag & PARODD )
+ smr |= SCI_ODD_PARITY ;
+ else
+ smr &= ~SCI_ODD_PARITY;
+
+ SH_SCI_REG_MASK((SCI_RE | SCI_TE), minor, SCI_SCR);
+
+ SH_SCI_REG_DATA(smr, minor, SCI_SMR);
+ SH_SCI_REG_DATA(brr, minor, SCI_BRR);
+
+ for (a=0; a < 10000L; a++) { /* Delay one bit */
+ __asm__ volatile ("nop");
+ }
+
+ SH_SCI_REG_FLAG((SCI_RE | SCI_TE), minor, SCI_SCR);
+
+ return 0;
+}
+
+/*
+ * Receive-data-full ISR
+ *
+ * The same routine for all interrupt sources of the same type.
+ */
+static rtems_isr sh_sci_rx_isr(rtems_vector_number vector)
+{
+ int minor;
+
+ for (minor = 0; minor < Console_Port_Count; minor++) {
+ if (Console_Port_Tbl[minor]->ulIntVector == vector) {
+ char temp8;
+
+ /*
+ * FIXME: error handling should be added
+ */
+ temp8 = read8(Console_Port_Tbl[minor]->ulCtrlPort1 + SCI_RDR);
+
+ rtems_termios_enqueue_raw_characters(
+ Console_Port_Data[minor].termios_data, &temp8, 1);
+
+ SH_SCI_REG_MASK(SCI_RDRF, minor, SCI_SSR);
+ break;
+ }
+ }
+}
+
+/*
+ * 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;
+ }
+ }
+}
+
+
+/*
+ * Initialization of serial port
+ */
+void sh_sci_init(int minor)
+{
+ uint16_t temp16;
+
+ /*
+ * set PFC registers to enable I/O pins
+ */
+ if ((minor == 0)) {
+ temp16 = read16(PFC_PACRL2); /* disable SCK0, DMA, IRQ */
+ temp16 &= ~(PA2MD1 | PA2MD0);
+ temp16 |= (PA_TXD0 | PA_RXD0); /* enable pins for Tx0, Rx0 */
+ write16(temp16, PFC_PACRL2);
+
+ } else if (minor == 1) {
+ temp16 = read16(PFC_PACRL2); /* disable SCK1, DMA, IRQ */
+ temp16 &= ~(PA5MD1 | PA5MD0);
+ temp16 |= (PA_TXD1 | PA_RXD1); /* enable pins for Tx1, Rx1 */
+ write16(temp16, PFC_PACRL2);
+ }
+
+ /*
+ * Non-default hardware setup occurs in sh_sci_first_open
+ */
+}
+
+/*
+ * Initialization of interrupts
+ *
+ * Interrupts can be started only after opening a device, so interrupt
+ * flags are set up in sh_sci_first_open function
+ */
+void sh_sci_initialize_interrupts(int minor)
+{
+ rtems_isr_entry old_isr;
+ rtems_status_code status;
+
+ sh_sci_init(minor);
+ /*
+ * Disable IRQ of SCIx
+ */
+ status = sh_set_irq_priority( Console_Port_Tbl[minor]->ulIntVector, 0);
+
+ if (status != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred(status);
+
+ SH_SCI_REG_MASK(SCI_RIE, minor, SCI_SCR);
+
+ /*
+ * Catch apropriate vectors
+ */
+ status = rtems_interrupt_catch(
+ sh_sci_rx_isr,
+ Console_Port_Tbl[minor]->ulIntVector,
+ &old_isr);
+
+ if (status != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred(status);
+
+ status = rtems_interrupt_catch(
+ sh_sci_tx_isr,
+ Console_Port_Tbl[minor]->ulDataPort,
+ &old_isr);
+
+ if (status != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred(status);
+
+ /*
+ * Enable IRQ of SCIx
+ */
+ SH_SCI_REG_FLAG(SCI_RIE, minor, SCI_SCR);
+
+ status = sh_set_irq_priority(
+ Console_Port_Tbl[minor]->ulIntVector,
+ Console_Port_Tbl[minor]->ulCtrlPort2);
+
+ if (status != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred(status);
+}
+
+
+/*
+ * Open entry point
+ * Sets up port and pins for selected sci.
+ */
+
+int sh_sci_first_open(
+ int major,
+ int minor,
+ void *arg
+)
+{
+ char temp8;
+ unsigned int a ;
+
+ /*
+ * check for valid minor number
+ */
+ if (( minor > ( SCI_MINOR_DEVICES -1 )) || ( minor < 0 )) {
+ return RTEMS_INVALID_NUMBER;
+ }
+
+ /*
+ * set up SCI registers
+ */
+ /* Clear SCR - disable Tx and Rx */
+ SH_SCI_REG_DATA(0x00, minor, SCI_SCR);
+
+ /* set SMR and BRR - baudrate and format */
+ sh_sci_set_attributes(minor, Console_Port_Tbl[minor]->pDeviceParams);
+
+ for (a=0; a < 10000L; a++) { /* Delay */
+ __asm__ volatile ("nop");
+ }
+
+ write8((SCI_RE | SCI_TE), /* enable async. Tx and Rx */
+ Console_Port_Tbl[minor]->ulCtrlPort1 + SCI_SCR);
+
+ /*
+ * clear error flags
+ */
+ temp8 = read8(Console_Port_Tbl[minor]->ulCtrlPort1 + SCI_SSR);
+ while(temp8 & (SCI_RDRF | SCI_ORER | SCI_FER | SCI_PER)) {
+ /* flush input */
+ temp8 = read8(Console_Port_Tbl[minor]->ulCtrlPort1 + SCI_RDR);
+
+ /* clear some flags */
+ SH_SCI_REG_FLAG((SCI_RDRF|SCI_ORER|SCI_FER|SCI_PER), minor, SCI_SSR);
+
+ /* check if everything is OK */
+ temp8 = read8(Console_Port_Tbl[minor]->ulCtrlPort1 + SCI_SSR);
+ }
+
+ /* Clear RDRF flag */
+ SH_SCI_REG_DATA(0x00, minor, SCI_TDR); /* force output */
+
+ /* Clear the TDRE bit */
+ SH_SCI_REG_FLAG(SCI_TDRE, minor, SCI_SSR);
+
+ /*
+ * Interrupt setup
+ */
+ if (Console_Port_Tbl[minor]->pDeviceFns->deviceOutputUsesInterrupts) {
+ SH_SCI_REG_FLAG(SCI_RIE, minor, SCI_SCR);
+ }
+
+ return RTEMS_SUCCESSFUL ;
+}
+
+/*
+ * Close entry point
+ */
+
+int sh_sci_last_close(
+ int major,
+ int minor,
+ void *arg
+)
+{
+ /* FIXME: Incomplete */
+
+ /* Shutdown interrupts if necessary */
+ if (Console_Port_Tbl[minor]->pDeviceFns->deviceOutputUsesInterrupts)
+ {
+ SH_SCI_REG_MASK((SCI_TIE | SCI_RIE), minor, SCI_SCR);
+ }
+ return RTEMS_SUCCESSFUL ;
+}
+
+/*
+ * Interrupt aware write routine
+ */
+ssize_t sh_sci_write_support_int(
+ int minor,
+ const char *buf,
+ size_t len
+)
+{
+ if (!len)
+ return 0;
+ /*
+ * Put data into TDR and clear transmission-end-flag
+ */
+ SH_SCI_REG_DATA(*buf, minor, SCI_TDR);
+ SH_SCI_REG_MASK(SCI_TDRE, minor, SCI_SSR);
+ /*
+ * Enable interrupt
+ */
+ SH_SCI_REG_FLAG(SCI_TIE, minor, SCI_SCR);
+
+ return 1;
+}
+
+/*
+ * Polled write method
+ */
+ssize_t sh_sci_write_support_polled(
+ int minor,
+ const char *buf,
+ size_t len
+)
+{
+ int count = 0;
+
+ while(count < len) {
+ sh_sci_write_polled(minor, buf[count]);
+ count++;
+ }
+ /*
+ * Return number of bytes written
+ */
+ return count;
+}
+
+/*
+ * Polled write of one character at a time
+ */
+void sh_sci_write_polled(
+ int minor,
+ char c
+)
+{
+ /*
+ * Wait for end of previous character
+ */
+ while(!(read8(Console_Port_Tbl[minor]->ulCtrlPort1 + SCI_SSR) & SCI_TDRE));
+ /*
+ * Send the character
+ */
+ SH_SCI_REG_DATA(c, minor, SCI_TDR);
+
+ /*
+ * Clear TDRE flag
+ */
+ SH_SCI_REG_MASK(SCI_TDRE, minor, SCI_SSR);
+}
+
+/*
+ * Non-blocking read
+ */
+int sh_sci_inbyte_nonblocking_polled(int minor)
+{
+ char inbyte;
+
+ /*
+ * Check if input buffer is full
+ */
+ if (read8(Console_Port_Tbl[minor]->ulCtrlPort1 + SCI_SSR) & SCI_RDRF) {
+ inbyte = read8(Console_Port_Tbl[minor]->ulCtrlPort1 + SCI_RDR);
+ SH_SCI_REG_MASK(SCI_RDRF, minor, SCI_SSR);
+
+ /*
+ * Check for errors
+ */
+ if (read8(Console_Port_Tbl[minor]->ulCtrlPort1 + SCI_SSR) &
+ (SCI_ORER | SCI_FER | SCI_PER)) {
+ SH_SCI_REG_MASK((SCI_ORER | SCI_FER | SCI_PER), minor, SCI_SSR);
+ return -1;
+ }
+ return (int)inbyte;
+ }
+ return -1;
+}
diff --git a/bsps/sh/gensh4/console/console.c b/bsps/sh/gensh4/console/console.c
new file mode 100644
index 0000000000..917556df4e
--- /dev/null
+++ b/bsps/sh/gensh4/console/console.c
@@ -0,0 +1,469 @@
+/*
+ * Console driver for SH-4 UART modules
+ *
+ * Copyright (C) 2000 OKTET Ltd., St.-Petersburg, Russia
+ * Author: Alexandra Kossovsky <sasha@oktet.ru>
+ *
+ * COPYRIGHT (c) 1989-1998.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <termios.h>
+
+#include <rtems/console.h>
+#include <rtems/libio.h>
+#include <bsp.h>
+
+#include "sh/sh4uart.h"
+
+/* Descriptor structures for two on-chip UART channels */
+sh4uart sh4_uarts[2];
+
+/* Console operations mode:
+ * 0 - raw (non-termios) polled input/output
+ * 1 - termios-based polled input/output
+ * 2 - termios-based interrupt-driven input/output
+ * 3 - non-termios over gdb stub
+ */
+int console_mode = 3;
+#define CONSOLE_MODE_RAW (0)
+#define CONSOLE_MODE_POLL (1)
+#define CONSOLE_MODE_INT (2)
+#define CONSOLE_MODE_IPL (3)
+
+/* Wrapper functions for SH-4 UART generic driver */
+
+/* console_poll_read --
+ * wrapper for poll read function
+ *
+ * PARAMETERS:
+ * minor - minor device number
+ *
+ * RETURNS:
+ * character code readed from UART, or -1 if there is no characters
+ * available
+ */
+static int
+console_poll_read(int minor)
+{
+ return sh4uart_poll_read(&sh4_uarts[minor]);
+}
+
+/* console_interrupt_write --
+ * wrapper for interrupt write function
+ *
+ * PARAMETERS:
+ * minor - minor device number
+ * buf - output buffer
+ * len - output buffer length
+ *
+ * RETURNS:
+ * result code
+ */
+static ssize_t
+console_interrupt_write(int minor, const char *buf, size_t len)
+{
+ return sh4uart_interrupt_write(&sh4_uarts[minor], buf, len);
+}
+
+/* console_poll_write --
+ * wrapper for polling mode write function
+ *
+ * PARAMETERS:
+ * minor - minor device number
+ * buf - output buffer
+ * len - output buffer length
+ *
+ * RETURNS:
+ * result code
+ */
+static ssize_t
+console_poll_write(int minor, const char *buf, size_t len)
+{
+ return sh4uart_poll_write(&sh4_uarts[minor], buf, len);
+}
+
+/* console_set_attributes --
+ * wrapper for hardware-dependent termios attributes setting
+ *
+ * PARAMETERS:
+ * minor - minor device number
+ * t - pointer to the termios structure
+ *
+ * RETURNS:
+ * result code
+ */
+static int
+console_set_attributes(int minor, const struct termios *t)
+{
+ return sh4uart_set_attributes(&sh4_uarts[minor], t);
+}
+
+/* console_stop_remote_tx --
+ * wrapper for stopping data flow from remote party.
+ *
+ * PARAMETERS:
+ * minor - minor device number
+ *
+ * RETURNS:
+ * result code
+ */
+static int
+console_stop_remote_tx(int minor)
+{
+ if (minor < sizeof(sh4_uarts)/sizeof(sh4_uarts[0]))
+ return sh4uart_stop_remote_tx(&sh4_uarts[minor]);
+ else
+ return RTEMS_INVALID_NUMBER;
+}
+
+/* console_start_remote_tx --
+ * wrapper for resuming data flow from remote party.
+ *
+ * PARAMETERS:
+ * minor - minor device number
+ *
+ */
+static int
+console_start_remote_tx(int minor)
+{
+ if (minor < sizeof(sh4_uarts)/sizeof(sh4_uarts[0]))
+ return sh4uart_start_remote_tx(&sh4_uarts[minor]);
+ else
+ return RTEMS_INVALID_NUMBER;
+}
+
+/* console_first_open --
+ * wrapper for UART controller initialization functions
+ *
+ * PARAMETERS:
+ * major - major device number
+ * minor - minor device number
+ * arg - libio device open argument
+ *
+ * RETURNS:
+ * error code
+ */
+static int
+console_first_open(int major, int minor, void *arg)
+{
+ rtems_libio_open_close_args_t *args = arg;
+ rtems_status_code sc;
+
+ sc = sh4uart_init(&sh4_uarts[minor], /* uart */
+ args->iop->data1, /* tty */
+ minor+1, /* channel */
+ (console_mode == CONSOLE_MODE_INT));
+
+ if (sc == RTEMS_SUCCESSFUL)
+ sc = sh4uart_reset(&sh4_uarts[minor]);
+
+ return sc;
+}
+
+/* console_last_close --
+ * wrapper for UART controller close function
+ *
+ * PARAMETERS:
+ * major - major device number
+ * minor - minor device number
+ * arg - libio device close argument
+ *
+ * RETURNS:
+ * error code
+ */
+static int
+console_last_close(int major, int minor, void *arg)
+{
+ if (console_mode != CONSOLE_MODE_IPL)
+ /* working from gdb we should not disable port operations */
+ return sh4uart_disable(&sh4_uarts[minor],
+ !(boot_mode == SH4_BOOT_MODE_IPL));
+ else
+ return RTEMS_SUCCESSFUL;
+}
+
+/* console_initialize --
+ * This routine initializes the console IO drivers and register devices
+ * in RTEMS I/O system.
+ *
+ * PARAMETERS:
+ * major - major console device number
+ * minor - minor console device number (not used)
+ * arg - device initialize argument
+ *
+ * RETURNS:
+ * RTEMS error code (RTEMS_SUCCESSFUL if device initialized successfuly)
+ */
+rtems_device_driver
+console_initialize(rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg)
+{
+ rtems_status_code status;
+
+#ifdef SH4_WITH_IPL
+ /* booting from flash we cannot have IPL console */
+ if (boot_mode != SH4_BOOT_MODE_IPL && console_mode == CONSOLE_MODE_IPL)
+ console_mode = CONSOLE_MODE_INT;
+
+ /* break out from gdb if neccessary */
+ if (boot_mode == SH4_BOOT_MODE_IPL && console_mode != CONSOLE_MODE_IPL)
+ ipl_finish();
+#endif
+
+ /*
+ * Set up TERMIOS
+ */
+ if ((console_mode != CONSOLE_MODE_RAW) &&
+ (console_mode != CONSOLE_MODE_IPL))
+ rtems_termios_initialize ();
+
+ /*
+ * Register the devices
+ */
+ status = rtems_io_register_name ("/dev/console", major, 0);
+ if (status != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (status);
+
+ status = rtems_io_register_name ("/dev/aux", major, 1);
+ if (status != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred (status);
+
+ if (console_mode == CONSOLE_MODE_RAW)
+ {
+ rtems_status_code sc;
+ sc = sh4uart_init(&sh4_uarts[0], /* uart */
+ NULL, /* tty */
+ 1, /* UART channel number */
+ 0); /* Poll-mode */
+
+ if (sc == RTEMS_SUCCESSFUL)
+ sc = sh4uart_reset(&sh4_uarts[0]);
+
+ sc = sh4uart_init(&sh4_uarts[1], /* uart */
+ NULL, /* tty */
+ 2, /* UART channel number */
+ 0); /* Poll-mode */
+
+ if (sc == RTEMS_SUCCESSFUL)
+ sc = sh4uart_reset(&sh4_uarts[1]);
+
+ return sc;
+ }
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/* console_open --
+ * Open console device driver. Pass appropriate termios callback
+ * functions to termios library.
+ *
+ * PARAMETERS:
+ * major - major device number for console devices
+ * minor - minor device number for console
+ * arg - device opening argument
+ *
+ * RETURNS:
+ * RTEMS error code
+ */
+rtems_device_driver
+console_open(rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg)
+{
+ static const rtems_termios_callbacks intr_callbacks = {
+ console_first_open, /* firstOpen */
+ console_last_close, /* lastClose */
+ NULL, /* pollRead */
+ console_interrupt_write, /* write */
+ console_set_attributes, /* setAttributes */
+ console_stop_remote_tx, /* stopRemoteTx */
+ console_start_remote_tx, /* startRemoteTx */
+ 1 /* outputUsesInterrupts */
+ };
+ static const rtems_termios_callbacks poll_callbacks = {
+ console_first_open, /* firstOpen */
+ console_last_close, /* lastClose */
+ console_poll_read, /* pollRead */
+ console_poll_write, /* write */
+ console_set_attributes, /* setAttributes */
+ console_stop_remote_tx, /* stopRemoteTx */
+ console_start_remote_tx, /* startRemoteTx */
+ 0 /* outputUsesInterrupts */
+ };
+
+ switch (console_mode)
+ {
+ case CONSOLE_MODE_RAW:
+ case CONSOLE_MODE_IPL:
+ return RTEMS_SUCCESSFUL;
+
+ case CONSOLE_MODE_INT:
+ return rtems_termios_open(major, minor, arg, &intr_callbacks);
+
+ case CONSOLE_MODE_POLL:
+ return rtems_termios_open(major, minor, arg, &poll_callbacks);
+
+ default:
+ rtems_fatal_error_occurred(0xC07A1310);
+ }
+
+ return RTEMS_INTERNAL_ERROR;
+}
+
+/* console_close --
+ * Close console device.
+ *
+ * PARAMETERS:
+ * major - major device number for console devices
+ * minor - minor device number for console
+ * arg - device close argument
+ *
+ * RETURNS:
+ * RTEMS error code
+ */
+rtems_device_driver
+console_close(rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg)
+{
+ if ((console_mode != CONSOLE_MODE_RAW) &&
+ (console_mode != CONSOLE_MODE_IPL))
+ return rtems_termios_close (arg);
+ else
+ return RTEMS_SUCCESSFUL;
+}
+
+/* console_read --
+ * Read from the console device
+ *
+ * PARAMETERS:
+ * major - major device number for console devices
+ * minor - minor device number for console
+ * arg - device read argument
+ *
+ * RETURNS:
+ * RTEMS error code
+ */
+rtems_device_driver
+console_read(rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg)
+{
+ if ((console_mode != CONSOLE_MODE_RAW) &&
+ (console_mode != CONSOLE_MODE_IPL))
+ {
+ return rtems_termios_read (arg);
+ }
+ else
+ {
+ rtems_libio_rw_args_t *argp = arg;
+ char *buf = argp->buffer;
+ int count = argp->count;
+ int n = 0;
+ int c;
+ while (n < count)
+ {
+ do {
+ c = (console_mode == CONSOLE_MODE_RAW) ?
+ sh4uart_poll_read(&sh4_uarts[minor]) :
+ ipl_console_poll_read(minor);
+ } while (c == -1);
+ if (c == '\r')
+ c = '\n';
+ *(buf++) = c;
+ n++;
+ if (c == '\n')
+ break;
+ }
+ argp->bytes_moved = n;
+ return RTEMS_SUCCESSFUL;
+ }
+}
+
+/* console_write --
+ * Write to the console device
+ *
+ * PARAMETERS:
+ * major - major device number for console devices
+ * minor - minor device number for console
+ * arg - device write argument
+ *
+ * RETURNS:
+ * RTEMS error code
+ */
+rtems_device_driver
+console_write(rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg)
+{
+ switch (console_mode)
+ {
+ case CONSOLE_MODE_POLL:
+ case CONSOLE_MODE_INT:
+ return rtems_termios_write (arg);
+ case CONSOLE_MODE_RAW:
+ {
+ rtems_libio_rw_args_t *argp = arg;
+ char cr = '\r';
+ char *buf = argp->buffer;
+ int count = argp->count;
+ int i;
+
+ for (i = 0; i < count; i++)
+ {
+ if (*buf == '\n')
+ sh4uart_poll_write(&sh4_uarts[minor], &cr, 1);
+ sh4uart_poll_write(&sh4_uarts[minor], buf, 1);
+ buf++;
+ }
+ argp->bytes_moved = count;
+ return RTEMS_SUCCESSFUL;
+ }
+#ifdef SH4_WITH_IPL
+ case CONSOLE_MODE_IPL:
+ {
+ rtems_libio_rw_args_t *argp = arg;
+ char *buf = argp->buffer;
+ int count = argp->count;
+ ipl_console_poll_write(minor, buf, count);
+ argp->bytes_moved = count;
+ return RTEMS_SUCCESSFUL;
+ }
+#endif
+ default: /* Unreachable */
+ return RTEMS_NOT_DEFINED;
+ }
+}
+
+/* console_control --
+ * Handle console device I/O control (IOCTL)
+ *
+ * PARAMETERS:
+ * major - major device number for console devices
+ * minor - minor device number for console
+ * arg - device ioctl argument
+ *
+ * RETURNS:
+ * RTEMS error code
+ */
+rtems_device_driver
+console_control(rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg)
+{
+ if ((console_mode != CONSOLE_MODE_RAW) &&
+ (console_mode != CONSOLE_MODE_IPL))
+ {
+ return rtems_termios_ioctl (arg);
+ }
+ else
+ {
+ return RTEMS_SUCCESSFUL;
+ }
+}
diff --git a/bsps/sh/gensh4/console/sh4uart.c b/bsps/sh/gensh4/console/sh4uart.c
new file mode 100644
index 0000000000..7acc1de337
--- /dev/null
+++ b/bsps/sh/gensh4/console/sh4uart.c
@@ -0,0 +1,910 @@
+/*
+ * Generic UART Serial driver for SH-4 processors
+ *
+ * Copyright (C) 2000 OKTET Ltd., St.-Petersburg, Russian Fed.
+ * Author: Alexandra Kossovsky <sasha@oktet.ru>
+ *
+ * COPYRIGHT (c) 1989-2000.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ *
+ */
+
+#include <rtems.h>
+#include <termios.h>
+#include <rtems/libio.h>
+#include <bsp.h>
+#include "sh/sh4uart.h"
+
+#ifndef SH4_UART_INTERRUPT_LEVEL
+#define SH4_UART_INTERRUPT_LEVEL 4
+#endif
+
+/* Forward function declarations */
+static rtems_isr
+sh4uart1_interrupt_transmit(rtems_vector_number vec);
+static rtems_isr
+sh4uart1_interrupt_receive(rtems_vector_number vec);
+static rtems_isr
+sh4uart2_interrupt_transmit(rtems_vector_number vec);
+static rtems_isr
+sh4uart2_interrupt_receive(rtems_vector_number vec);
+
+/*
+ * sh4uart_init --
+ * This function verifies the input parameters and perform initialization
+ * of the SH-4 on-chip UART descriptor structure.
+ *
+ * PARAMETERS:
+ * uart - pointer to the UART channel descriptor structure
+ * tty - pointer to termios structure
+ * chn - channel number (SH4_SCI/SH4_SCIF -- 1/2)
+ * int_driven - interrupt-driven (1) or polled (0) I/O mode
+ *
+ * RETURNS:
+ * RTEMS_SUCCESSFUL if all parameters are valid, or error code
+ */
+rtems_status_code
+sh4uart_init(sh4uart *uart, void *tty, int chn, int int_driven)
+{
+ if (uart == NULL)
+ return RTEMS_INVALID_ADDRESS;
+
+ if ((chn != SH4_SCI) && (chn != SH4_SCIF))
+ return RTEMS_INVALID_NUMBER;
+
+ uart->chn = chn;
+ uart->tty = tty;
+ uart->int_driven = int_driven;
+
+#if 0
+ sh4uart_poll_write(uart, "init", 4);
+#endif
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * sh4uart_get_Pph --
+ * Get current peripheral module clock.
+ *
+ * PARAMETERS: none;
+ * Cpu clock is get from CPU_CLOCK_RATE_HZ marco
+ * (defined in bspopts.h, included from bsp.h)
+ *
+ * RETURNS:
+ * peripheral module clock in Hz.
+ */
+static uint32_t
+sh4uart_get_Pph(void)
+{
+ uint16_t frqcr = *(volatile uint16_t*)SH7750_FRQCR;
+ uint32_t Pph = CPU_CLOCK_RATE_HZ;
+
+ switch (frqcr & SH7750_FRQCR_IFC) {
+ case SH7750_FRQCR_IFCDIV1: break;
+ case SH7750_FRQCR_IFCDIV2: Pph *= 2; break;
+ case SH7750_FRQCR_IFCDIV3: Pph *= 3; break;
+ case SH7750_FRQCR_IFCDIV4: Pph *= 4; break;
+ case SH7750_FRQCR_IFCDIV6: Pph *= 6; break;
+ case SH7750_FRQCR_IFCDIV8: Pph *= 8; break;
+ default: /* unreachable */
+ break;
+ }
+
+ switch (frqcr & SH7750_FRQCR_PFC) {
+ case SH7750_FRQCR_PFCDIV2: Pph /= 2; break;
+ case SH7750_FRQCR_PFCDIV3: Pph /= 3; break;
+ case SH7750_FRQCR_PFCDIV4: Pph /= 4; break;
+ case SH7750_FRQCR_PFCDIV6: Pph /= 6; break;
+ case SH7750_FRQCR_PFCDIV8: Pph /= 8; break;
+ default: /* unreachable */
+ break;
+ }
+
+ return Pph;
+}
+
+/*
+ * sh4uart_set_baudrate --
+ * Program the UART timer to specified baudrate
+ *
+ * PARAMETERS:
+ * uart - pointer to UART descriptor structure
+ * baud - termios baud rate (B50, B9600, etc...)
+ *
+ * ALGORITHM:
+ * see SH7750 Hardware Manual.
+ *
+ * RETURNS:
+ * none
+ */
+static void
+sh4uart_set_baudrate(sh4uart *uart, speed_t baud)
+{
+ uint32_t rate;
+ int16_t div;
+ int n;
+ uint32_t Pph = sh4uart_get_Pph();
+
+ switch (baud) {
+ case B50: rate = 50; break;
+ case B75: rate = 75; break;
+ case B110: rate = 110; break;
+ case B134: rate = 134; break;
+ case B150: rate = 150; break;
+ case B200: rate = 200; break;
+ case B300: rate = 300; break;
+ case B600: rate = 600; break;
+ case B1200: rate = 1200; break;
+ case B2400: rate = 2400; break;
+ case B4800: rate = 4800; break;
+ case B9600: rate = 9600; break;
+ case B19200: rate = 19200; break;
+ case B38400: rate = 38400; break;
+ case B57600: rate = 57600; break;
+#ifdef B115200
+ case B115200: rate = 115200; break;
+#endif
+#ifdef B230400
+ case B230400: rate = 230400; break;
+#endif
+ default: rate = 9600; break;
+ }
+
+ for (n = 0; n < 4; n++) {
+ div = Pph / (32 * (1 << (2 * n)) * rate) - 1;
+ if (div < 0x100)
+ break;
+ }
+
+ /* Set default baudrate if specified baudrate is impossible */
+ if (n >= 4)
+ sh4uart_set_baudrate(uart, B9600);
+
+ if ( uart->chn == 1 ) {
+ volatile uint8_t *smr1 = (volatile uint8_t *)SH7750_SCSMR1;
+ *smr1 &= ~SH7750_SCSMR_CKS;
+ *smr1 |= n << SH7750_SCSMR_CKS_S;
+ } else {
+ volatile uint16_t *smr2 = (volatile uint16_t *)SH7750_SCSMR2;
+ *smr2 &= ~SH7750_SCSMR_CKS;
+ *smr2 |= n << SH7750_SCSMR_CKS_S;
+ }
+
+ SCBRR(uart->chn) = div;
+ /* Wait at least 1 bit interwal */
+ rtems_task_wake_after(RTEMS_MILLISECONDS_TO_TICKS(1000 / rate));
+}
+
+/*
+ * sh4uart_reset --
+ * This function perform the hardware initialization of SH-4
+ * on-chip UART controller using parameters
+ * filled by the sh4uart_init function.
+ *
+ * PARAMETERS:
+ * uart - pointer to UART channel descriptor structure
+ *
+ * RETURNS:
+ * RTEMS_SUCCESSFUL if channel is initialized successfully, error
+ * code in other case
+ */
+rtems_status_code
+sh4uart_reset(sh4uart *uart)
+{
+ register int chn;
+ register int int_driven;
+ rtems_status_code rc;
+ uint16_t tmp;
+
+ if (uart == NULL)
+ return RTEMS_INVALID_ADDRESS;
+
+ chn = uart->chn;
+ int_driven = uart->int_driven;
+
+ if ( chn == 1 ) {
+ volatile uint8_t *scr1 = (volatile uint8_t *)SH7750_SCSCR1;
+ volatile uint8_t *smr1 = (volatile uint8_t *)SH7750_SCSMR1;
+ *scr1 = 0x0; /* Is set properly at the end of this function */
+ *smr1 = 0x0; /* 8-bit, non-parity, 1 stop bit, pf/1 clock */
+ } else {
+ volatile uint16_t *scr2 = (volatile uint16_t *)SH7750_SCSCR2;
+ volatile uint16_t *smr2 = (volatile uint16_t *)SH7750_SCSMR2;
+ *scr2 = 0x0; /* Is set properly at the end of this function */
+ *smr2 = 0x0; /* 8-bit, non-parity, 1 stop bit, pf/1 clock */
+ }
+
+ if (chn == SH4_SCIF)
+ SCFCR2 = SH7750_SCFCR2_TFRST | SH7750_SCFCR2_RFRST |
+ SH7750_SCFCR2_RTRG_1 | SH7750_SCFCR2_TTRG_4;
+
+ if (chn == SH4_SCI)
+ SCSPTR1 = int_driven ? 0x0 : SH7750_SCSPTR1_EIO;
+ else
+ SCSPTR2 = SH7750_SCSPTR2_RTSDT;
+
+ if (int_driven) {
+ uint16_t ipr;
+
+ if (chn == SH4_SCI) {
+ ipr = IPRB;
+ ipr &= ~SH7750_IPRB_SCI1;
+ ipr |= SH4_UART_INTERRUPT_LEVEL << SH7750_IPRB_SCI1_S;
+ IPRB = ipr;
+
+ rc = rtems_interrupt_catch(sh4uart1_interrupt_transmit,
+ SH7750_EVT_TO_NUM(SH7750_EVT_SCI_TXI),
+ &uart->old_handler_transmit);
+ if (rc != RTEMS_SUCCESSFUL)
+ return rc;
+
+ rc = rtems_interrupt_catch(sh4uart1_interrupt_receive,
+ SH7750_EVT_TO_NUM(SH7750_EVT_SCI_RXI),
+ &uart->old_handler_receive);
+ if (rc != RTEMS_SUCCESSFUL)
+ return rc;
+ } else {
+ ipr = IPRC;
+ ipr &= ~SH7750_IPRC_SCIF;
+ ipr |= SH4_UART_INTERRUPT_LEVEL << SH7750_IPRC_SCIF_S;
+ IPRC = ipr;
+
+ rc = rtems_interrupt_catch(sh4uart2_interrupt_transmit,
+ SH7750_EVT_TO_NUM(SH7750_EVT_SCIF_TXI),
+ &uart->old_handler_transmit);
+ if (rc != RTEMS_SUCCESSFUL)
+ return rc;
+ rc = rtems_interrupt_catch(sh4uart2_interrupt_receive,
+ SH7750_EVT_TO_NUM(SH7750_EVT_SCIF_RXI),
+ &uart->old_handler_receive);
+ if (rc != RTEMS_SUCCESSFUL)
+ return rc;
+ }
+ uart->tx_buf = NULL;
+ uart->tx_ptr = uart->tx_buf_len = 0;
+ }
+
+ sh4uart_set_baudrate(uart, B38400); /* debug defaults (unfortunately,
+ it is differ to termios default */
+
+ tmp = SH7750_SCSCR_TE | SH7750_SCSCR_RE |
+ (chn == SH4_SCI ? 0x0 : SH7750_SCSCR2_REIE) |
+ (int_driven ? (SH7750_SCSCR_RIE | SH7750_SCSCR_TIE) : 0x0);
+
+ if ( chn == 1 ) {
+ volatile uint8_t *scr = (volatile uint8_t *)SH7750_SCSCR1;
+ *scr = tmp;
+ } else {
+ volatile uint16_t *scr = (volatile uint16_t *)SH7750_SCSCR2;
+ *scr = tmp;
+ }
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * sh4uart_disable --
+ * This function disable the operations on SH-4 UART controller
+ *
+ * PARAMETERS:
+ * uart - pointer to UART channel descriptor structure
+ * disable_port - disable receive and transmit on the port
+ *
+ * RETURNS:
+ * RTEMS_SUCCESSFUL if UART closed successfuly, or error code in
+ * other case
+ */
+rtems_status_code
+sh4uart_disable(sh4uart *uart, int disable_port)
+{
+ rtems_status_code rc;
+
+ if (disable_port) {
+ if ( uart->chn == 1 ) {
+ volatile uint8_t *scr = (volatile uint8_t *)SH7750_SCSCR1;
+ *scr &= ~(SH7750_SCSCR_TE | SH7750_SCSCR_RE);
+ } else {
+ volatile uint16_t *scr = (volatile uint16_t *)SH7750_SCSCR2;
+ *scr &= ~(SH7750_SCSCR_TE | SH7750_SCSCR_RE);
+ }
+ }
+
+ if (uart->int_driven) {
+ rc = rtems_interrupt_catch(uart->old_handler_transmit,
+ uart->chn == SH4_SCI ? SH7750_EVT_SCI_TXI : SH7750_EVT_SCIF_TXI,
+ NULL);
+ if (rc != RTEMS_SUCCESSFUL)
+ return rc;
+ rc = rtems_interrupt_catch(uart->old_handler_receive,
+ uart->chn == SH4_SCI ? SH7750_EVT_SCI_RXI : SH7750_EVT_SCIF_RXI,
+ NULL);
+ if (rc != RTEMS_SUCCESSFUL)
+ return rc;
+ }
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * sh4uart_set_attributes --
+ * This function parse the termios attributes structure and perform
+ * the appropriate settings in hardware.
+ *
+ * PARAMETERS:
+ * uart - pointer to the UART descriptor structure
+ * t - pointer to termios parameters
+ *
+ * RETURNS:
+ * RTEMS_SUCCESSFUL
+ */
+rtems_status_code
+sh4uart_set_attributes(sh4uart *uart, const struct termios *t)
+{
+ int level;
+ speed_t baud;
+ uint16_t smr;
+
+ smr = (uint16_t)(*(uint8_t*)SH7750_SCSMR(uart->chn));
+
+ baud = cfgetospeed(t);
+
+ /* Set flow control XXX*/
+ if ((t->c_cflag & CRTSCTS) != 0) {
+ }
+
+ /* Set character size -- only 7 or 8 bit */
+ switch (t->c_cflag & CSIZE) {
+ case CS5:
+ case CS6:
+ case CS7: smr |= SH7750_SCSMR_CHR_7; break;
+ case CS8: smr &= ~SH7750_SCSMR_CHR_7; break;
+ }
+
+ /* Set number of stop bits */
+ if ((t->c_cflag & CSTOPB) != 0)
+ smr |= SH7750_SCSMR_STOP_2;
+ else
+ smr &= ~SH7750_SCSMR_STOP_2;
+
+ /* Set parity mode */
+ if ((t->c_cflag & PARENB) != 0) {
+ smr |= SH7750_SCSMR_PE;
+ if ((t->c_cflag & PARODD) != 0)
+ smr |= SH7750_SCSMR_PM_ODD;
+ else
+ smr &= ~SH7750_SCSMR_PM_ODD;
+ } else
+ smr &= ~SH7750_SCSMR_PE;
+
+ rtems_interrupt_disable(level);
+ /* wait untill all data is transmitted */
+ /* XXX JOEL says this is broken -- interrupts are OFF so NO ticks */
+ rtems_task_wake_after(RTEMS_MILLISECONDS_TO_TICKS(100));
+
+ if ( uart->chn == 1 ) {
+ volatile uint8_t *scrP = (volatile uint8_t *)SH7750_SCSCR1;
+ volatile uint8_t *smrP = (volatile uint8_t *)SH7750_SCSMR1;
+
+ *scrP &= ~(SH7750_SCSCR_TE | SH7750_SCSCR_RE); /* disable operations */
+ sh4uart_set_baudrate(uart, baud);
+ *smrP = (uint8_t)smr;
+ *scrP |= SH7750_SCSCR_TE | SH7750_SCSCR_RE; /* enable operations */
+ } else {
+ volatile uint16_t *scrP = (volatile uint16_t *)SH7750_SCSCR2;
+ volatile uint16_t *smrP = (volatile uint16_t *)SH7750_SCSMR2;
+
+ *scrP &= ~(SH7750_SCSCR_TE | SH7750_SCSCR_RE); /* disable operations */
+ sh4uart_set_baudrate(uart, baud);
+ *smrP = (uint8_t)smr;
+ *scrP |= SH7750_SCSCR_TE | SH7750_SCSCR_RE; /* enable operations */
+ }
+
+ rtems_interrupt_enable(level);
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * sh4uart_handle_error --
+ * Perfoms error (Overrun, Framing & Parity) handling
+ *
+ * PARAMETERS:
+ * uart - pointer to UART descriptor structure
+ *
+ * RETURNS:
+ * nothing
+ */
+static void
+sh4uart_handle_error(sh4uart *uart)
+{
+ if (uart->chn == SH4_SCI) {
+ volatile uint8_t *scr = (volatile uint8_t *)SH7750_SCSCR1;
+ *scr &= ~(SH7750_SCSSR1_ORER | SH7750_SCSSR1_FER | SH7750_SCSSR1_PER);
+ } else {
+ volatile uint16_t *scr = (volatile uint16_t *)SH7750_SCSCR2;
+ *scr &= ~(SH7750_SCSSR2_ER | SH7750_SCSSR2_BRK | SH7750_SCSSR2_FER);
+ *scr &= ~(SH7750_SCLSR2_ORER);
+ }
+}
+
+/*
+ * sh4uart_poll_read --
+ * This function tried to read character from SH-4 UART and perform
+ * error handling. When parity or framing error occured, return
+ * value dependent on termios input mode flags:
+ * - received character, if IGNPAR == 1
+ * - 0, if IGNPAR == 0 and PARMRK == 0
+ * - 0xff and 0x00 on next poll_read invocation, if IGNPAR == 0 and
+ * PARMRK == 1
+ *
+ * PARAMETERS:
+ * uart - pointer to UART descriptor structure
+ *
+ * RETURNS:
+ * code of received character or -1 if no characters received.
+ */
+int
+sh4uart_poll_read(sh4uart *uart)
+{
+ int chn = uart->chn;
+ int parity_error = 0;
+ int break_occured = 0;
+ int ch;
+
+ if (uart->parerr_mark_flag == true) {
+ uart->parerr_mark_flag = false;
+ return 0;
+ }
+
+ if (chn == SH4_SCI) {
+ if ((SCSSR1 & (SH7750_SCSSR1_PER | SH7750_SCSSR1_FER |
+ SH7750_SCSSR1_ORER)) != 0) {
+ if (SCSSR1 & (SH7750_SCSSR1_PER | SH7750_SCSSR1_FER))
+ parity_error = 1;
+ sh4uart_handle_error(uart);
+ }
+ if ((SCSSR1 & SH7750_SCSSR1_RDRF) == 0)
+ return -1;
+ } else {
+ if ((SCSSR2 & (SH7750_SCSSR2_ER | SH7750_SCSSR2_DR |
+ SH7750_SCSSR2_BRK)) != 0 ||
+ (SCLSR2 & SH7750_SCLSR2_ORER) != 0) {
+ if (SCSSR2 & (SH7750_SCSSR1_PER | SH7750_SCSSR1_FER))
+ parity_error = 1;
+ if (SCSSR2 & SH7750_SCSSR2_BRK)
+ break_occured = 1;
+ sh4uart_handle_error(uart);
+ }
+ if ((SCSSR2 & SH7750_SCSSR2_RDF) == 0)
+ return -1;
+ }
+
+ if (parity_error && !(uart->c_iflag & IGNPAR)) {
+ if (uart->c_iflag & PARMRK) {
+ uart->parerr_mark_flag = true;
+ return 0xff;
+ } else
+ return 0;
+ }
+
+ if (break_occured && !(uart->c_iflag & BRKINT)) {
+ if (uart->c_iflag & IGNBRK)
+ return 0;
+ else
+ return 0; /* XXX -- SIGINT */
+ }
+
+ ch = SCRDR(chn);
+
+ if (uart->chn == SH4_SCI) {
+ volatile uint8_t *scr = (volatile uint8_t *)SH7750_SCSCR1;
+ *scr &= ~SH7750_SCSSR1_RDRF;
+ } else {
+ volatile uint16_t *scr = (volatile uint16_t *)SH7750_SCSCR2;
+ *scr &= ~SH7750_SCSSR2_RDF;
+ }
+
+ return ch;
+}
+
+/*
+ * sh4uart_poll_write --
+ * This function transmit buffer byte-by-byte in polling mode.
+ *
+ * PARAMETERS:
+ * uart - pointer to the UART descriptor structure
+ * buf - pointer to transmit buffer
+ * len - transmit buffer length
+ *
+ * RETURNS:
+ * 0
+ */
+int
+sh4uart_poll_write(sh4uart *uart, const char *buf, int len)
+{
+ volatile uint8_t *ssr1 = (volatile uint8_t *)SH7750_SCSSR1;
+ volatile uint16_t *ssr2 = (volatile uint16_t *)SH7750_SCSSR2;
+
+ while (len) {
+ if (uart->chn == SH4_SCI) {
+ while ((SCSSR1 & SH7750_SCSSR1_TDRE) != 0) {
+ SCTDR1 = *buf++;
+ len--;
+ *ssr1 &= ~SH7750_SCSSR1_TDRE;
+ }
+ } else {
+ while ((SCSSR2 & SH7750_SCSSR2_TDFE) != 0) {
+ int i;
+ for (i = 0;
+ i < 16 - TRANSMIT_TRIGGER_VALUE(SCFCR2 &
+ SH7750_SCFCR2_TTRG);
+ i++) {
+ SCTDR2 = *buf++;
+ len--;
+ }
+ while ((SCSSR2 & SH7750_SCSSR2_TDFE) == 0 ||
+ (SCSSR2 & SH7750_SCSSR2_TEND) == 0);
+ *ssr2 &= ~(SH7750_SCSSR1_TDRE | SH7750_SCSSR2_TEND);
+ }
+ }
+ }
+ return 0;
+}
+
+/**********************************
+ * Functions to handle interrupts *
+ **********************************/
+/* sh4uart1_interrupt_receive --
+ * UART interrupt handler routine -- SCI
+ * Receiving data
+ *
+ * PARAMETERS:
+ * vec - interrupt vector number
+ *
+ * RETURNS:
+ * none
+ */
+static rtems_isr
+sh4uart1_interrupt_receive(rtems_vector_number vec)
+{
+ register int bp = 0;
+ char buf[32];
+ volatile uint8_t *ssr1 = (volatile uint8_t *)SH7750_SCSSR1;
+
+
+ /* Find UART descriptor from vector number */
+ sh4uart *uart = &sh4_uarts[0];
+
+ while (1) {
+ if ((bp < sizeof(buf) - 1) && ((SCSSR1 & SH7750_SCSSR1_RDRF) != 0)) {
+ /* Receive character and handle frame/parity errors */
+ if ((SCSSR1 & (SH7750_SCSSR1_PER | SH7750_SCSSR1_FER |
+ SH7750_SCSSR1_ORER)) != 0) {
+ if (SCSSR1 & (SH7750_SCSSR1_PER | SH7750_SCSSR1_FER)) {
+ if (!(uart->c_iflag & IGNPAR)) {
+ if (uart->c_iflag & PARMRK) {
+ buf[bp++] = 0xff;
+ buf[bp++] = 0x00;
+ } else
+ buf[bp++] = 0x00;
+ } else
+ buf[bp++] = SCRDR1;
+ }
+ sh4uart_handle_error(uart);
+ } else
+ buf[bp++] = SCRDR1;
+ *ssr1 &= ~SH7750_SCSSR1_RDRF;
+ } else {
+ if (bp != 0)
+ rtems_termios_enqueue_raw_characters(uart->tty, buf, bp);
+ break;
+ }
+ }
+}
+
+/* sh4uart2_interrupt_receive --
+ * UART interrupt handler routine -- SCIF
+ * Receiving data
+ *
+ * PARAMETERS:
+ * vec - interrupt vector number
+ *
+ * RETURNS:
+ * none
+ */
+static rtems_isr
+sh4uart2_interrupt_receive(rtems_vector_number vec)
+{
+ register int bp = 0;
+ char buf[32];
+ volatile uint16_t *ssr2 = (volatile uint16_t *)SH7750_SCSSR2;
+
+
+ /* Find UART descriptor from vector number */
+ sh4uart *uart = &sh4_uarts[1];
+
+ while (1) {
+ if ((bp < sizeof(buf) - 1) && ((SCSSR2 & SH7750_SCSSR2_RDF) != 0)) {
+ if ((SCSSR2 & (SH7750_SCSSR2_ER | SH7750_SCSSR2_DR |
+ SH7750_SCSSR2_BRK)) != 0 ||
+ (SH7750_SCLSR2 & SH7750_SCLSR2_ORER) != 0) {
+ if (SCSSR2 & SH7750_SCSSR2_ER) {
+ if (!(uart->c_iflag & IGNPAR)) {
+ if (uart->c_iflag & PARMRK) {
+ buf[bp++] = 0xff;
+ buf[bp++] = 0x00;
+ } else
+ buf[bp++] = 0x00;
+ } else
+ buf[bp++] = SCRDR1;
+ }
+
+ if (SCSSR2 & SH7750_SCSSR2_BRK) {
+ if (uart->c_iflag & IGNBRK)
+ buf[bp++] = 0x00;
+ else
+ buf[bp++] = 0x00; /* XXX -- SIGINT */
+ }
+
+ sh4uart_handle_error(uart);
+ } else
+ buf[bp++] = SCRDR1;
+ *ssr2 &= ~SH7750_SCSSR2_RDF;
+ } else {
+ if (bp != 0)
+ rtems_termios_enqueue_raw_characters(uart->tty, buf, bp);
+ break;
+ }
+ }
+}
+
+
+/* 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);
+ }
+}
+
+/* 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);
+ }
+}
+
+/* sh4uart_interrupt_write --
+ * This function initiate transmitting of the buffer in interrupt mode.
+ *
+ * PARAMETERS:
+ * uart - pointer to the UART descriptor structure
+ * buf - pointer to transmit buffer
+ * len - transmit buffer length
+ *
+ * RETURNS:
+ * 0
+ */
+rtems_status_code
+sh4uart_interrupt_write(sh4uart *uart, const char *buf, int len)
+{
+ if (len > 0) {
+ volatile uint8_t *scr1 = (volatile uint8_t *)SH7750_SCSCR1;
+ volatile uint16_t *scr2 = (volatile uint16_t *)SH7750_SCSCR2;
+
+ while ((SCSSR1 & SH7750_SCSSR1_TEND) == 0);
+
+ uart->tx_buf = buf;
+ uart->tx_buf_len = len;
+ uart->tx_ptr = 0;
+
+ if (uart->chn == SH4_SCI)
+ *scr1 |= SH7750_SCSCR_TIE;
+ else
+ *scr2 |= SH7750_SCSCR_TIE;
+ }
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/* sh4uart_stop_remote_tx --
+ * This function stop data flow from remote device.
+ *
+ * PARAMETERS:
+ * uart - pointer to the UART descriptor structure
+ *
+ * RETURNS:
+ * RTEMS_SUCCESSFUL
+ */
+rtems_status_code
+sh4uart_stop_remote_tx(sh4uart *uart)
+{
+ if ( uart->chn == 1 ) {
+ volatile uint8_t *scr = (volatile uint8_t *)SH7750_SCSCR1;
+ *scr &= ~(SH7750_SCSCR_RIE | SH7750_SCSCR_RE);
+ } else {
+ volatile uint16_t *scr = (volatile uint16_t *)SH7750_SCSCR2;
+ *scr &= ~(SH7750_SCSCR_RIE | SH7750_SCSCR_RE);
+ }
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/* sh4uart_start_remote_tx --
+ * This function resume data flow from remote device.
+ *
+ * PARAMETERS:
+ * uart - pointer to the UART descriptor structure
+ *
+ * RETURNS:
+ * RTEMS_SUCCESSFUL
+ */
+rtems_status_code
+sh4uart_start_remote_tx(sh4uart *uart)
+{
+ if ( uart->chn == 1 ) {
+ volatile uint8_t *scr = (volatile uint8_t *)SH7750_SCSCR1;
+ *scr |= SH7750_SCSCR_RIE | SH7750_SCSCR_RE;
+ } else {
+ volatile uint16_t *scr = (volatile uint16_t *)SH7750_SCSCR2;
+ *scr |= SH7750_SCSCR_RIE | SH7750_SCSCR_RE;
+ }
+
+ return RTEMS_SUCCESSFUL;
+}
+
+#ifdef SH4_WITH_IPL
+/*********************************
+ * Functions for SH-IPL gdb stub *
+ *********************************/
+
+/*
+ * ipl_finish --
+ * Says gdb that program finished to get out from it.
+ */
+extern void ipl_finish(void);
+__asm__ (
+" .global _ipl_finish\n"
+"_ipl_finish:\n"
+" mov.l __ipl_finish_value, r0\n"
+" trapa #0x3f\n"
+" nop\n"
+" rts\n"
+" nop\n"
+" .align 4\n"
+"__ipl_finish_value:\n"
+" .long 255"
+);
+
+extern int ipl_serial_input(int poll_count);
+__asm__ (
+" .global _ipl_serial_input\n"
+"_ipl_serial_input:\n"
+" mov #1,r0\n"
+" trapa #0x3f\n"
+" nop\n"
+" rts\n"
+" nop\n");
+
+extern void ipl_serial_output(const char *buf, int len);
+__asm__ (
+" .global _ipl_serial_output\n"
+"_ipl_serial_output:\n"
+" mov #0,r0\n"
+" trapa #0x3f\n"
+" nop\n"
+" rts\n"
+" nop\n");
+
+/* ipl_console_poll_read --
+ * poll read operation for simulator console through ipl mechanism.
+ *
+ * PARAMETERS:
+ * minor - minor device number
+ *
+ * RETURNS:
+ * character code red from UART, or -1 if there is no characters
+ * available
+ */
+int
+ipl_console_poll_read(int minor)
+{
+ unsigned char buf;
+ buf = ipl_serial_input(0x100000);
+ return buf;
+}
+
+/* ipl_console_poll_write --
+ * wrapper for polling mode write function
+ *
+ * PARAMETERS:
+ * minor - minor device number
+ * buf - output buffer
+ * len - output buffer length
+ *
+ * RETURNS:
+ * result code (0)
+ */
+int
+ipl_console_poll_write(int minor, const char *buf, int len)
+{
+ int c;
+ while (len > 0) {
+ c = (len < 64 ? len : 64);
+ ipl_serial_output(buf, c);
+ len -= c;
+ buf += c;
+ }
+ return 0;
+}
+#endif
diff --git a/bsps/sh/shsim/console/console-debugio.c b/bsps/sh/shsim/console/console-debugio.c
new file mode 100644
index 0000000000..0a81dbe45b
--- /dev/null
+++ b/bsps/sh/shsim/console/console-debugio.c
@@ -0,0 +1,33 @@
+/**
+ * @file
+ * @brief Stub printk() support
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2014.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+/*
+ * To support printk
+ */
+
+#include <rtems.h>
+#include <rtems/bspIo.h>
+
+void console_outbyte_polled(
+ int port,
+ char ch
+);
+
+static void BSP_output_char_f(char c)
+{
+ console_outbyte_polled( 0, c );
+}
+
+BSP_output_char_function_type BSP_output_char = BSP_output_char_f;
+BSP_polling_getchar_function_type BSP_poll_char = NULL;
diff --git a/bsps/sh/shsim/console/console-io.c b/bsps/sh/shsim/console/console-io.c
new file mode 100644
index 0000000000..71b089fdf7
--- /dev/null
+++ b/bsps/sh/shsim/console/console-io.c
@@ -0,0 +1,57 @@
+/*
+ * This file contains the hardware specific portions of the TTY driver
+ * for the simulators stdin/out.
+ */
+
+/*
+ * COPYRIGHT (c) 1989-2011.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <bsp.h>
+#include <bsp/console-polled.h>
+#include <rtems/libio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include <bsp/syscall.h>
+
+/*
+ * console_initialize_hardware
+ *
+ * This routine initializes the console hardware.
+ */
+void console_initialize_hardware(void)
+{
+}
+
+/*
+ * console_outbyte_polled
+ *
+ * This routine transmits a character using polling.
+ */
+void console_outbyte_polled(
+ int port,
+ char ch
+)
+{
+ __trap34 (SYS_write, 1, &ch, 1);
+}
+
+/*
+ * console_inbyte_nonblocking
+ *
+ * This routine polls for a character.
+ */
+int console_inbyte_nonblocking(
+ int port
+)
+{
+ unsigned char c;
+
+ return __trap34 (SYS_read, 0, &c, 1);
+}
diff --git a/bsps/sh/shsim/console/console-support.S b/bsps/sh/shsim/console/console-support.S
new file mode 100644
index 0000000000..63f72f794b
--- /dev/null
+++ b/bsps/sh/shsim/console/console-support.S
@@ -0,0 +1,18 @@
+/*
+ * newlib-1.8.2/newlib/libc/sys/sh/trap.S
+ */
+ .text
+ .global ___trap34
+___trap34:
+ trapa #34
+ tst r1,r1 ! r1 is errno
+ bt ret
+ mov.l perrno,r2
+ mov.l r1,@r2
+ret:
+ rts
+ nop
+
+ .align 2
+perrno:
+ .long _errno