summaryrefslogtreecommitdiffstats
path: root/bsps/powerpc/gen5200
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/powerpc/gen5200
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/powerpc/gen5200')
-rw-r--r--bsps/powerpc/gen5200/console/console.c835
1 files changed, 835 insertions, 0 deletions
diff --git a/bsps/powerpc/gen5200/console/console.c b/bsps/powerpc/gen5200/console/console.c
new file mode 100644
index 0000000000..d7325032c4
--- /dev/null
+++ b/bsps/powerpc/gen5200/console/console.c
@@ -0,0 +1,835 @@
+/*===============================================================*\
+| Project: RTEMS generic MPC5200 BSP |
++-----------------------------------------------------------------+
+| Partially based on the code references which are named below. |
+| Adaptions, modifications, enhancements and any recent parts of |
+| the code are: |
+| Copyright (c) 2005 |
+| Embedded Brains GmbH |
+| Obere Lagerstr. 30 |
+| D-82178 Puchheim |
+| Germany |
+| rtems@embedded-brains.de |
++-----------------------------------------------------------------+
+| 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. |
+| |
++-----------------------------------------------------------------+
+| this file contains the console driver functions |
+\*===============================================================*/
+/***********************************************************************/
+/* */
+/* Module: console.c */
+/* Date: 07/17/2003 */
+/* Purpose: RTEMS MPC5x00 console driver */
+/* */
+/*---------------------------------------------------------------------*/
+/* */
+/* Description: */
+/* */
+/* The PSCs of mpc5200 are assigned as follows */
+/* */
+/* Channel Device Minor Note */
+/* PSC1 /dev/tty0 0 */
+/* PSC2 /dev/tty1 1 */
+/* PSC3 /dev/tty2 2 */
+/* */
+/*---------------------------------------------------------------------*/
+/* */
+/* Code */
+/* References: Serial driver for MPC8260ads */
+/* Module: console-generic.c */
+/* Project: RTEMS 4.6.0pre1 / MPC8260ads BSP */
+/* Version 1.3 */
+/* Date: 2002/11/04 */
+/* */
+/* Author(s) / Copyright(s): */
+/* */
+/* Author: Jay Monkman (jmonkman@frasca.com) */
+/* Copyright (C) 1998 by Frasca International, Inc. */
+/* */
+/* Derived from c/src/lib/libbsp/m68k/gen360/console/console.c */
+/* written by: */
+/* W. Eric Norum */
+/* Saskatchewan Accelerator Laboratory */
+/* University of Saskatchewan */
+/* Saskatoon, Saskatchewan, CANADA */
+/* eric@skatter.usask.ca */
+/* */
+/* COPYRIGHT (c) 1989-2008. */
+/* On-Line Applications Research Corporation (OAR). */
+/* */
+/* Modifications by Darlene Stewart <Darlene.Stewart@iit.nrc.ca> */
+/* and Charles-Antoine Gauthier <charles.gauthier@iit.nrc.ca> */
+/* Copyright (c) 1999, National Research Council of Canada */
+/* */
+/* Modifications by Andy Dachs <a.dachs@sstl.co.uk> to add MPC8260 */
+/* support. */
+/* Copyright (c) 2001, Surrey Satellite Technology Ltd */
+/* */
+/* 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. */
+/* */
+/*---------------------------------------------------------------------*/
+/* */
+/* Partially based on the code references which are named above. */
+/* Adaptions, modifications, enhancements and any recent parts of */
+/* the code are under the right of */
+/* */
+/* IPR Engineering, Dachauer Straße 38, D-80335 München */
+/* Copyright(C) 2003 */
+/* */
+/*---------------------------------------------------------------------*/
+/* */
+/* IPR Engineering makes no representation or warranties with */
+/* respect to the performance of this computer program, and */
+/* specifically disclaims any responsibility for any damages, */
+/* special or consequential, connected with the use of this program. */
+/* */
+/*---------------------------------------------------------------------*/
+/* */
+/* Version history: 1.0 */
+/* */
+/***********************************************************************/
+
+#include <assert.h>
+#include <string.h>
+
+#include <rtems.h>
+#include <bsp/mpc5200.h>
+#include <bsp.h>
+#include <bsp/irq.h>
+
+#include <rtems/console.h>
+#include <rtems/bspIo.h>
+#include <rtems/libio.h>
+#include <rtems/termiostypes.h>
+
+
+#define NUM_PORTS MPC5200_PSC_NO
+
+#define PSC1_MINOR 0
+#define PSC2_MINOR 1
+#define PSC3_MINOR 2
+#define PSC4_MINOR 3
+#define PSC5_MINOR 4
+#define PSC6_MINOR 5
+
+uint32_t mpc5200_uart_avail_mask = BSP_UART_AVAIL_MASK;
+
+#if defined(UARTS_USE_TERMIOS_INT)
+ uint8_t psc_minor_to_irqname[NUM_PORTS] = {
+ BSP_SIU_IRQ_PSC1,
+ BSP_SIU_IRQ_PSC2,
+ BSP_SIU_IRQ_PSC3,
+ BSP_SIU_IRQ_PSC4,
+ BSP_SIU_IRQ_PSC5,
+ BSP_SIU_IRQ_PSC6
+ };
+
+ static int mpc5200_psc_irqname_to_minor(int name) {
+ int minor;
+ uint8_t *chrptr;
+
+ chrptr = memchr(psc_minor_to_irqname, name, sizeof(psc_minor_to_irqname));
+ if (chrptr != NULL) {
+ minor = chrptr - psc_minor_to_irqname;
+ } else {
+ minor = -1;
+ }
+ return minor;
+ }
+#endif
+
+static void A_BSP_output_char(char c);
+static int A_BSP_get_char(void);
+BSP_output_char_function_type BSP_output_char = A_BSP_output_char;
+
+BSP_polling_getchar_function_type BSP_poll_char = A_BSP_get_char;
+
+/* Used to handle premature outputs of printk */
+bool console_initialized = false;
+
+/* per channel info structure */
+struct per_channel_info {
+ uint16_t shadow_imr;
+ uint8_t shadow_mode1;
+ uint8_t shadow_mode2;
+ int cur_tx_len;
+ int rx_interrupts;
+ int tx_interrupts;
+ int rx_characters;
+ int tx_characters;
+ int breaks_detected;
+ int framing_errors;
+ int parity_errors;
+ int overrun_errors;
+};
+
+/* Used to handle more than one channel */
+struct per_channel_info channel_info[NUM_PORTS];
+
+/*
+ * XXX: there are only 6 PSCs, but PSC6 has an extra register gap
+ * from PSC5, therefore we instantiate seven(!) PSC register sets
+ */
+uint8_t psc_minor_to_regset[MPC5200_PSC_NO] = {0,1,2,3,4,6};
+
+/* Used to track termios private data for callbacks */
+struct rtems_termios_tty *ttyp[NUM_PORTS];
+
+static int mpc5200_psc_setAttributes(
+ int minor,
+ const struct termios *t
+)
+{
+ int baud;
+ uint8_t csize=0, cstopb, parenb, parodd;
+ struct mpc5200_psc *psc =
+ (struct mpc5200_psc *)(&mpc5200.psc[psc_minor_to_regset[minor]]);
+
+ /* Baud rate */
+ baud = rtems_termios_baud_to_number(t->c_ospeed);
+ if (baud > 0) {
+ /*
+ * Calculate baud rate
+ * round divider to nearest!
+ */
+ baud = (IPB_CLOCK + baud *16) / (baud * 32);
+ }
+
+ /* Number of data bits */
+ switch ( t->c_cflag & CSIZE ) {
+ case CS5: csize = 0x00; break;
+ case CS6: csize = 0x01; break;
+ case CS7: csize = 0x02; break;
+ case CS8: csize = 0x03; break;
+ }
+
+ /* Stop bits */
+ if(csize == 0) {
+ if(t->c_cflag & CSTOPB)
+ cstopb = 0x0F; /* Two stop bits */
+ else
+ cstopb = 0x00; /* One stop bit */
+ } else {
+ if(t->c_cflag & CSTOPB)
+ cstopb = 0x0F; /* Two stop bits */
+ else
+ cstopb = 0x07; /* One stop bit */
+ }
+
+ /* Parity */
+ if (t->c_cflag & PARENB)
+ parenb = 0x00; /* Parity enabled on Tx and Rx */
+ else
+ parenb = 0x10; /* No parity on Tx and Rx */
+
+ if (t->c_cflag & PARODD)
+ parodd = 0x04; /* Odd parity */
+ else
+ parodd = 0x00;
+
+ /*
+ * Set upper timer counter
+ */
+ psc->ctur = (uint8_t) (baud >> 8);
+
+ /*
+ * Set lower timer counter
+ */
+ psc->ctlr = (uint8_t) baud;
+
+ /*
+ * Reset mode pointer
+ */
+ psc->cr = ((1 << 4) << 8);
+
+ /*
+ * Set mode1 register
+ */
+ channel_info[minor].shadow_mode1 &= ~(0x1F);
+ psc->mr = channel_info[minor].shadow_mode1 | (csize | parenb | parodd);
+
+ /*
+ * Set mode2 register
+ */
+ channel_info[minor].shadow_mode2 &= ~(0x0F);
+ psc->mr = channel_info[minor].shadow_mode2 | cstopb;
+
+ return 0;
+
+}
+
+
+static int mpc5200_uart_setAttributes(int minor, const struct termios *t)
+{
+ /*
+ * Check that port number is valid
+ */
+ if( (minor < PSC1_MINOR) || (minor > NUM_PORTS-1) )
+ return 0;
+
+ return mpc5200_psc_setAttributes(minor, t);
+
+}
+
+#ifdef UARTS_USE_TERMIOS_INT
+/*
+ * Interrupt handlers
+ */
+static void mpc5200_psc_interrupt_handler(rtems_irq_hdl_param handle)
+{
+ unsigned char c;
+ uint16_t isr;
+ int minor = (int)handle;
+ struct mpc5200_psc *psc =
+ (struct mpc5200_psc *)(&mpc5200.psc[psc_minor_to_regset[minor]]);
+
+ /*
+ * get content of psc interrupt status
+ */
+ isr = psc->isr_imr;
+
+ /*
+ * Character received?
+ */
+ if (isr & ISR_RX_RDY_FULL) {
+
+ channel_info[minor].rx_interrupts++;
+
+
+#ifndef SINGLE_CHAR_MODE
+ while(psc->rfnum) {
+#endif
+ /*
+ * get the character
+ */
+ c = (psc->rb_tb >> 24);
+
+ if (ttyp[minor] != NULL) {
+ rtems_termios_enqueue_raw_characters(
+ (void *)ttyp[minor], (char *)&c, (int)1);
+ channel_info[minor].rx_characters++;
+ }
+
+#ifndef SINGLE_CHAR_MODE
+ }
+#endif
+
+ }
+
+ /*
+ * Character transmitted ?
+ */
+ if (isr & ISR_TX_RDY & channel_info[minor].shadow_imr) {
+ channel_info[minor].tx_interrupts++;
+
+ if (ttyp[minor] != NULL) {
+ #ifndef SINGLE_CHAR_MODE
+ rtems_termios_dequeue_characters(
+ (void *)ttyp[minor], channel_info[minor].cur_tx_len);
+ channel_info[minor].tx_characters += channel_info[minor].cur_tx_len;
+ #else
+ rtems_termios_dequeue_characters((void *)ttyp[minor], (int)1);
+ channel_info[minor].tx_characters++;
+ #endif
+ }
+ }
+
+ if(isr & ISR_ERROR) {
+ if(isr & ISR_RB)
+ channel_info[minor].breaks_detected++;
+ if(isr & ISR_FE)
+ channel_info[minor].framing_errors++;
+ if(isr & ISR_PE)
+ channel_info[minor].parity_errors++;
+ if(isr & ISR_OE)
+ channel_info[minor].overrun_errors++;
+
+ /*
+ * Reset error status
+ */
+ psc->cr = ((4 << 4) << 8);
+ }
+}
+
+static void mpc5200_psc_enable(
+ const rtems_irq_connect_data* ptr
+)
+{
+ struct mpc5200_psc *psc;
+ int minor = mpc5200_psc_irqname_to_minor(ptr->name);
+
+ if (minor >= 0) {
+ psc = (struct mpc5200_psc *)(&mpc5200.psc[psc_minor_to_regset[minor]]);
+ psc->isr_imr = channel_info[minor].shadow_imr |=
+ (IMR_RX_RDY_FULL | IMR_TX_RDY);
+ }
+}
+
+
+static void mpc5200_psc_disable(
+ const rtems_irq_connect_data* ptr
+)
+{
+ struct mpc5200_psc *psc;
+ int minor = mpc5200_psc_irqname_to_minor(ptr->name);
+
+ if (minor >= 0) {
+ psc = (struct mpc5200_psc *)(&mpc5200.psc[psc_minor_to_regset[minor]]);
+ psc->isr_imr = channel_info[minor].shadow_imr &=
+ ~(IMR_RX_RDY_FULL | IMR_TX_RDY);
+ }
+}
+
+static int mpc5200_psc_isOn(
+ const rtems_irq_connect_data* ptr
+)
+{
+ struct mpc5200_psc *psc;
+ int minor = mpc5200_psc_irqname_to_minor(ptr->name);
+
+ if (minor >= 0) {
+ psc = (struct mpc5200_psc *)(&mpc5200.psc[psc_minor_to_regset[minor]]);
+ return ((psc->isr_imr & IMR_RX_RDY_FULL) & (psc->isr_imr & IMR_TX_RDY));
+ }
+ return false;
+}
+
+
+static rtems_irq_connect_data consoleIrqData;
+#endif
+
+static void mpc5200_uart_psc_initialize(
+ int minor
+)
+{
+ uint32_t baud_divider;
+ struct mpc5200_psc *psc =
+ (struct mpc5200_psc *)(&mpc5200.psc[psc_minor_to_regset[minor]]);
+
+ /*
+ * Check that minor number is valid
+ */
+ if ((minor < PSC1_MINOR) || (minor >= (PSC1_MINOR + NUM_PORTS)))
+ return;
+
+ /*
+ * Clear per channel info
+ */
+ memset((void *)&channel_info[minor], 0, sizeof(struct per_channel_info));
+
+ /*
+ * Reset receiver and transmitter
+ */
+ psc->cr = ((2 << 4) << 8);
+ psc->cr = ((3 << 4) << 8);
+
+ /*
+ * Reset mode pointer
+ */
+ psc->cr = ((1 << 4) << 8);
+
+ /*
+ * Set clock select register
+ */
+ psc->sr_csr = 0;
+
+ /*
+ * Set mode1 register
+ */
+ psc->mr = channel_info[minor].shadow_mode1 = 0x33; /* 8Bit / no parity */
+
+ /*
+ * Set mode2 register
+ */
+ psc->mr = channel_info[minor].shadow_mode2 = 7; /* 1 stop bit */
+
+ /*
+ * Set rx FIFO alarm
+ */
+ psc->rfalarm = RX_FIFO_SIZE - 1;
+
+ /*
+ * Set tx FIFO alarm
+ */
+ psc->tfalarm = 1;
+
+ baud_divider =
+ (IPB_CLOCK + GEN5200_CONSOLE_BAUD *16) / (GEN5200_CONSOLE_BAUD * 32);
+
+ /*
+ * Set upper timer counter
+ */
+ psc->ctur = baud_divider >> 16;
+
+ /*
+ * Set lower timer counter
+ */
+
+ psc->ctlr = baud_divider & 0x0000ffff;
+
+ /*
+ * Disable Frame mode / set granularity 0
+ */
+ psc->tfcntl = 0;
+
+#ifdef UARTS_USE_TERMIOS_INT
+ /*
+ * Tie interrupt dependent routines
+ */
+ consoleIrqData.on = mpc5200_psc_enable;
+ consoleIrqData.off = mpc5200_psc_disable;
+ consoleIrqData.isOn = mpc5200_psc_isOn;
+ consoleIrqData.handle = (rtems_irq_hdl_param)minor;
+ consoleIrqData.hdl = (rtems_irq_hdl)mpc5200_psc_interrupt_handler;
+
+ /*
+ * Tie interrupt handler
+ */
+ consoleIrqData.name = psc_minor_to_irqname[minor];
+
+ /*
+ * Install rtems irq handler
+ */
+ assert(BSP_install_rtems_irq_handler(&consoleIrqData) == 1);
+#endif
+
+ /*
+ * Reset rx fifo errors Error/UF/OF
+ */
+ psc->rfstat |= 0x70;
+
+ /*
+ * Reset tx fifo errors Error/UF/OF
+ */
+ psc->tfstat |= 0x70;
+
+#ifdef UARTS_USE_TERMIOS_INT
+ /*
+ * Unmask receive interrupt
+ */
+ psc->isr_imr = channel_info[minor].shadow_imr = IMR_RX_RDY_FULL;
+#endif
+
+ /*
+ * Enable receiver
+ */
+ psc->cr = ((1 << 0) << 8);
+
+ /*
+ * Enable transmitter
+ */
+ psc->cr = ((1 << 2) << 8);
+}
+
+
+static int mpc5200_uart_pollRead(
+ int minor
+)
+{
+ unsigned char c;
+ struct mpc5200_psc *psc =
+ (struct mpc5200_psc *)(&mpc5200.psc[psc_minor_to_regset[minor]]);
+
+ if (psc->sr_csr & (1 << 8))
+ c = (psc->rb_tb >> 24);
+ else
+ return -1;
+
+ return c;
+}
+
+
+static ssize_t mpc5200_uart_pollWrite(
+ int minor,
+ const char *buf,
+ size_t len
+)
+{
+ size_t retval = len;
+ const char *tmp_buf = buf;
+ struct mpc5200_psc *psc =
+ (struct mpc5200_psc *)(&mpc5200.psc[psc_minor_to_regset[minor]]);
+
+ while(len--) {
+ while(!(psc->sr_csr & (1 << 11)))
+ continue;
+
+ /*rtems_cache_flush_multiple_data_lines( (void *)buf, 1);*/
+
+ psc->rb_tb = (*tmp_buf << 24);
+
+ tmp_buf++;
+
+ }
+ return retval;
+
+}
+
+static ssize_t mpc5200_uart_write(
+ int minor,
+ const char *buf,
+ size_t len
+)
+{
+ struct mpc5200_psc *psc =
+ (struct mpc5200_psc *)(&mpc5200.psc[psc_minor_to_regset[minor]]);
+
+ if (len > 0) {
+ int frame_len = len;
+ const char *frame_buf = buf;
+
+ /*
+ * Check tx fifo space
+ */
+ if(len > (TX_FIFO_SIZE - psc->tfnum))
+ frame_len = TX_FIFO_SIZE - psc->tfnum;
+
+#ifndef SINGLE_CHAR_MODE
+ channel_info[minor].cur_tx_len = frame_len;
+#else
+ frame_len = 1;
+#endif
+
+ /*rtems_cache_flush_multiple_data_lines( (void *)frame_buf, frame_len);*/
+
+ while (frame_len--)
+ /* perform byte write to avoid extra NUL characters */
+ (* (volatile char *)&(psc->rb_tb)) = *frame_buf++;
+
+ /*
+ * unmask interrupt
+ */
+ psc->isr_imr = channel_info[minor].shadow_imr |= IMR_TX_RDY;
+ } else {
+ /*
+ * mask interrupt
+ */
+ psc->isr_imr = channel_info[minor].shadow_imr &= ~(IMR_TX_RDY);
+ }
+
+ return 0;
+}
+
+/*
+ * Print functions prototyped in bspIo.h
+ */
+static void A_BSP_output_char(
+ char c
+)
+{
+ /*
+ * If we are using U-Boot, then the console is already initialized
+ * and we can just poll bytes out at any time.
+ */
+ #if !defined(HAS_UBOOT)
+ if (console_initialized == false)
+ return;
+ #endif
+
+#define PRINTK_WRITE mpc5200_uart_pollWrite
+
+ PRINTK_WRITE(PRINTK_MINOR, &c, 1 );
+}
+
+static int A_BSP_get_char(void)
+{
+ /*
+ * If we are using U-Boot, then the console is already initialized
+ * and we can just poll bytes in at any time.
+ */
+ #if !defined(HAS_UBOOT)
+ if (console_initialized == false)
+ return -1;
+ #endif
+
+ return mpc5200_uart_pollRead(0);
+}
+
+/*
+ ***************
+ * BOILERPLATE *
+ ***************
+ *
+ * All these functions are prototyped in rtems/c/src/lib/include/console.h.
+ */
+
+/*
+ * Initialize and register the device
+ */
+rtems_device_driver console_initialize(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg
+)
+{
+ rtems_status_code status;
+ rtems_device_minor_number console_minor;
+ char dev_name[] = "/dev/ttyx";
+ uint32_t tty_num = 0;
+ bool first = true;
+
+ /*
+ * Always use and set up TERMIOS
+ */
+ console_minor = PSC1_MINOR;
+ rtems_termios_initialize();
+
+ for (console_minor = PSC1_MINOR;
+ console_minor < PSC1_MINOR + NUM_PORTS;
+ console_minor++) {
+ /*
+ * check, whether UART is available for this board
+ */
+ if (0 != ((1 << console_minor) & (mpc5200_uart_avail_mask))) {
+ /*
+ * Do device-specific initialization and registration for Motorola IceCube
+ */
+ mpc5200_uart_psc_initialize(console_minor); /* /dev/tty0 */
+ dev_name[8] = '0' + tty_num;
+ status = rtems_io_register_name (dev_name, major, console_minor);
+ assert(status == RTEMS_SUCCESSFUL);
+
+ #ifdef MPC5200_PSC_INDEX_FOR_GPS_MODULE
+ if (console_minor == MPC5200_PSC_INDEX_FOR_GPS_MODULE) {
+ status = rtems_io_register_name("/dev/gps", major, console_minor);
+ assert(status == RTEMS_SUCCESSFUL);
+ }
+ #endif
+
+ if (first) {
+ first = false;
+
+ /* Now register the RTEMS console */
+ status = rtems_io_register_name ("/dev/console", major, console_minor);
+ assert(status == RTEMS_SUCCESSFUL);
+ }
+
+ tty_num++;
+ }
+ }
+
+ console_initialized = true;
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * Open the device
+ */
+rtems_device_driver console_open(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg
+)
+{
+ rtems_libio_open_close_args_t *args = arg;
+ rtems_status_code sc;
+
+#ifdef UARTS_USE_TERMIOS_INT
+ static const rtems_termios_callbacks intrCallbacks = {
+ NULL, /* firstOpen */
+ NULL, /* lastClose */
+ NULL, /* pollRead */
+ mpc5200_uart_write, /* write */
+ mpc5200_uart_setAttributes, /* setAttributes */
+ NULL,
+ NULL,
+ 1 /* outputUsesInterrupts */
+ };
+#else
+ static const rtems_termios_callbacks pollCallbacks = {
+ NULL, /* firstOpen */
+ NULL, /* lastClose */
+ mpc5200_uart_pollRead, /* pollRead */
+ mpc5200_uart_pollWrite, /* write */
+ mpc5200_uart_setAttributes, /* setAttributes */
+ NULL,
+ NULL,
+ 0 /* output don't use Interrupts */
+ };
+#endif
+
+ if(minor > NUM_PORTS - 1)
+ return RTEMS_INVALID_NUMBER;
+
+#ifdef UARTS_USE_TERMIOS_INT
+ sc = rtems_termios_open( major, minor, arg, &intrCallbacks );
+#else /* RTEMS polled I/O with termios */
+ sc = rtems_termios_open( major, minor, arg, &pollCallbacks );
+#endif
+
+ ttyp[minor] = args->iop->data1; /* Keep cookie returned by termios_open */
+
+ if ( !sc )
+ rtems_termios_set_initial_baud( ttyp[minor], GEN5200_CONSOLE_BAUD );
+
+ return sc;
+}
+
+
+/*
+ * Close the device
+ */
+rtems_device_driver console_close(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg
+)
+{
+ if ( minor > NUM_PORTS-1 )
+ return RTEMS_INVALID_NUMBER;
+
+ ttyp[minor] = NULL; /* mark for int handler: tty no longer open */
+
+ return rtems_termios_close( arg );
+}
+
+
+/*
+ * Read from the device
+ */
+rtems_device_driver console_read(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg
+)
+{
+ if(minor > NUM_PORTS-1)
+ return RTEMS_INVALID_NUMBER;
+
+ return rtems_termios_read(arg);
+}
+
+/*
+ * Write to the device
+ */
+rtems_device_driver console_write(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg
+)
+{
+ if ( minor > NUM_PORTS-1 )
+ return RTEMS_INVALID_NUMBER;
+ return rtems_termios_write(arg);
+}
+
+/*
+ * Handle ioctl request.
+ */
+rtems_device_driver console_control(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg
+)
+{
+ if ( minor > NUM_PORTS-1 )
+ return RTEMS_INVALID_NUMBER;
+
+ return rtems_termios_ioctl(arg);
+}