summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/sh/gensh2/console
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2017-12-08 13:31:12 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2017-12-08 13:31:12 +0100
commit533e2c0af6dad96de5c8123206adebea2fbb06d2 (patch)
treefdff3fdd8c09aac5b809d672399c634062871662 /c/src/lib/libbsp/sh/gensh2/console
parentbsp/gensh1: Move libcpu files to BSP (diff)
downloadrtems-533e2c0af6dad96de5c8123206adebea2fbb06d2.tar.bz2
bsp/gensh2: Move libcpu files to BSP
Update #3254.
Diffstat (limited to 'c/src/lib/libbsp/sh/gensh2/console')
-rw-r--r--c/src/lib/libbsp/sh/gensh2/console/sci.c554
-rw-r--r--c/src/lib/libbsp/sh/gensh2/console/sci_termios.c449
2 files changed, 1003 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/sh/gensh2/console/sci.c b/c/src/lib/libbsp/sh/gensh2/console/sci.c
new file mode 100644
index 0000000000..143fc1bb94
--- /dev/null
+++ b/c/src/lib/libbsp/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/c/src/lib/libbsp/sh/gensh2/console/sci_termios.c b/c/src/lib/libbsp/sh/gensh2/console/sci_termios.c
new file mode 100644
index 0000000000..5d588065af
--- /dev/null
+++ b/c/src/lib/libbsp/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;
+}