summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/m68k/mvme162/consolex/consolex.c
diff options
context:
space:
mode:
authorJoel Sherrill <joel.sherrill@OARcorp.com>1997-08-01 18:12:11 +0000
committerJoel Sherrill <joel.sherrill@OARcorp.com>1997-08-01 18:12:11 +0000
commit9deb5b8b2822eb49c7a31d35d37d9b59dcd6555c (patch)
tree2797615f5f5eab05772d2bb807ba95e0d632481b /c/src/lib/libbsp/m68k/mvme162/consolex/consolex.c
parentMerged very large and much appreciated patch from Chris Johns (diff)
downloadrtems-9deb5b8b2822eb49c7a31d35d37d9b59dcd6555c.tar.bz2
Katsutoshi Shibuya (shibuya@mxb.meshnet.or.jp)of BU-Denken Co., Ltd.
(Sapporo, Japan) submitted the extended console driver for the MVME162LX BSP and the POSIX tcsetattr() and tcgetattr() routines. This device driver supports four serial ports, cooked IO, and provides a portable base for Zilog 8530 based console drivers.
Diffstat (limited to 'c/src/lib/libbsp/m68k/mvme162/consolex/consolex.c')
-rw-r--r--c/src/lib/libbsp/m68k/mvme162/consolex/consolex.c786
1 files changed, 786 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/m68k/mvme162/consolex/consolex.c b/c/src/lib/libbsp/m68k/mvme162/consolex/consolex.c
new file mode 100644
index 0000000000..c868954d12
--- /dev/null
+++ b/c/src/lib/libbsp/m68k/mvme162/consolex/consolex.c
@@ -0,0 +1,786 @@
+/*
+ * This file contains the MVME162LX extended console IO package.
+ *
+ * This file was created originally by
+ * On-Line Applications Research Corporation (OAR)
+ * and modified by:
+ *
+ * Katsutoshi Shibuya - BU-Denken Co.,Ltd. - Sapporo, JAPAN
+ *
+ * featuring support of:
+ *
+ * - Multi-SCC chip handling
+ * - Non-blocking I/O (O_NDELAY flag in libc)
+ * - Raw mode device (no CR/LF detection)
+ * - RTS/CTS flow control
+ *
+ * REMARKS: This routine requires multiple interrupt vectors
+ * from SCC_VECTOR (normaly 0x40)
+ * to SCC_VECTOR+(number of SCC chips)
+ *
+ * The original copyright follows;
+ *
+ * COPYRIGHT (c) 1989-1997.
+ * On-Line Applications Research Corporation (OAR).
+ * Copyright assigned to U.S. Government, 1994.
+ *
+ * The license and distribution terms for this file may in
+ * the file LICENSE in this distribution or at
+ * http://www.OARcorp.com/rtems/license.html.
+ *
+ * Modifications of respective RTEMS file: COPYRIGHT (c) 1994.
+ * EISCAT Scientific Association. M.Savitski
+ *
+ * This material is a part of the MVME162 Board Support Package
+ * for the RTEMS executive. Its licensing policies are those of the
+ * RTEMS above.
+ *
+ */
+
+#define M162_INIT
+
+#include "consolex.h"
+#include <bsp.h>
+#include <rtems/libio.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#define NPORTS 4 /* Number of ports */
+#define DEVICEPREFIX "tty"
+#define RAWDEVICEPREFIX "rtty"
+#define CONSOLEPORT 0 /* port# of console:
+ undef this if you do not want /dev/console */
+#define READRETRY 1 /* Maximum retry count for read one char */
+#define WRITERETRY 8 /* Maximum retry count for write one char */
+
+#define PORTFROM 0 /* for debug */
+
+static unsigned char opencount[NPORTS];
+
+/***********************************************************************
+ Ring buffer for device
+ ***********************************************************************/
+
+#define QUEUE_LENGTH 128 /* Must be 2^n number */
+
+typedef struct {
+ char buffer[QUEUE_LENGTH];
+ volatile int head;
+ volatile int tail;
+} ReceiverBuffer;
+
+#define ReceiverBufferInitialize( _buffer ) \
+ do { \
+ (_buffer)->head = (_buffer)->tail = 0; \
+ } while ( 0 )
+
+#define ReceiverBufferIsEmpty( _buffer ) \
+ ( (_buffer)->tail == (_buffer)->head )
+
+#define ReceiverBufferIsNearEmpty( _buffer ) \
+ ( (_buffer)->tail == (((_buffer)->head + 3) & (QUEUE_LENGTH-1)) )
+
+#define ReceiverBufferIsFull( _buffer ) \
+ ( (_buffer)->head == (((_buffer)->tail + 1) & (QUEUE_LENGTH-1)) )
+
+#define ReceiverBufferIsNearFull( _buffer ) \
+ ( (_buffer)->head == (((_buffer)->tail + 3) & (QUEUE_LENGTH-1)) )
+
+#define ReceiverBufferAdd( _buffer, _ch ) \
+ do { \
+ rtems_unsigned32 isrlevel; \
+ \
+ rtems_interrupt_disable( isrlevel ); \
+ (_buffer)->tail = ((_buffer)->tail+1) & (QUEUE_LENGTH-1); \
+ (_buffer)->buffer[ (_buffer)->tail ] = (_ch); \
+ rtems_interrupt_enable( isrlevel ); \
+ } while ( 0 )
+
+#define ReceiverBufferRemove( _buffer, _ch ) \
+ do { \
+ rtems_unsigned32 isrlevel; \
+ \
+ rtems_interrupt_disable( isrlevel ); \
+ (_buffer)->head = ((_buffer)->head+1) & (QUEUE_LENGTH-1); \
+ (_ch) = (_buffer)->buffer[ (_buffer)->head ]; \
+ rtems_interrupt_enable( isrlevel ); \
+ } while ( 0 )
+
+
+/***********************************************************************
+ DEVICE DEPENDED PART
+ ***********************************************************************/
+
+
+/* Time constant parameters
+ CAUTION: These parameters are for MVME162LX-213 board.
+ */
+
+#define TC38400 0x0006
+#define TC19200 0x000e
+#define TC9600 0x001e
+
+/* Re-defining SCC register control macros
+ to support Multi SCC chips */
+
+#undef scc
+static scc_regs *scc[NPORTS] = {
+ ((scc_regs * const) 0xFFF45004),
+ ((scc_regs * const) 0xFFF45000),
+ ((scc_regs * const) 0xFFF45804),
+ ((scc_regs * const) 0xFFF45800)
+};
+
+#undef ZWRITE0
+#define ZWRITE0(port, v) (scc[port]->csr = (unsigned char)(v))
+#undef ZREAD0
+#define ZREAD0(port) (scc[port]->csr)
+
+#undef ZREAD
+#define ZREAD(port, n) (ZWRITE0(port, n), (scc[port]->csr))
+#undef ZREADD
+#define ZREADD(port) (scc[port]->csr=0x08, scc[port]->csr )
+
+#undef ZWRITE
+#define ZWRITE(port, n, v) (ZWRITE0(port, n), ZWRITE0(port, v))
+#undef ZWRITED
+#define ZWRITED(port, v) (scc[port]->csr = 0x08, \
+ scc[port]->csr = (unsigned char)(v))
+
+static ReceiverBuffer receiverBuffer[NPORTS];
+
+/*
+ * Control flags (DTR/DCD/RTS/CTS)
+ */
+
+static unsigned char wr4[NPORTS];
+static unsigned char wr5[NPORTS];
+#define SCCSetDTR(port) ZWRITE(port, 5, (wr5[port] |= 0x80))
+#define SCCResetDTR(port) ZWRITE(port, 5, (wr5[port] &= ~0x80))
+#define SCCSetRTS(port) ZWRITE(port, 5, (wr5[port] |= 0x02))
+#define SCCResetRTS(port) ZWRITE(port,5, (wr5[port] &= ~0x02))
+#define SCCGetDCD(port) (ZREAD0(port)&0x08)
+#define SCCGetCTS(port) (ZREAD0(port)&0x20)
+
+
+/*
+ * Interrupt handler for receiver interrupts
+ */
+
+static rtems_isr SCCReceiverISR(rtems_vector_number vector)
+{
+ register int ipend, port;
+
+ port = (vector-SCC_VECTOR)*2;
+ ZWRITE0(port, 0x38); /* reset highest IUS */
+
+ ipend = ZREAD(port, 3); /* read int pending from A side */
+
+ if(ipend == 0x04)
+ port++; /* channel B intr pending */
+ else if(ipend == 0x20)
+ ; /* channel A intr pending */
+ else
+ return;
+
+ ReceiverBufferAdd(&receiverBuffer[port], ZREADD(port));
+
+ if(ZREAD(port,1) & 0x70){ /* check error stat */
+ ZWRITE0(port, 0x30); /* reset error */
+ }
+
+ if(ReceiverBufferIsNearFull(&receiverBuffer[port]))
+ SCCResetRTS(port);
+}
+
+/*
+ * Initialize
+ */
+
+void SCCInitialize()
+{
+ int i;
+
+ for(i = PORTFROM; i < NPORTS; i+=2)
+ ZWRITE(i, 9,0xc0); /* Reset SCC Chip */
+
+ for(i = PORTFROM; i < NPORTS; i++){
+ ReceiverBufferInitialize(&(receiverBuffer[i]));
+ wr4[i] = 0x44;
+ ZWRITE(i, 4, wr4[i]); /* x16 clock, 1 stop, parity none */
+ ZWRITE(i, 1, 0); /* disable interrupts */
+ ZWRITE(i, 2, SCC_VECTOR+(i/2));
+ ZWRITE(i, 3, 0xc1); /* receiver enable, 8bits */
+ wr5[i] = 0x68;
+ ZWRITE(i, 5, wr5[i]); /* transmitter enable, 8bits, DTR&RTS off */
+ ZWRITE(i,14, 0); /* stop baudrate gen. */
+ ZWRITE(i,11,0x50); /* use baurate gen. */
+ ZWRITE(i,15, 1); /* Select WR7' */
+ ZWRITE(i, 7, 0); /* Disable all special interrupts */
+ ZWRITE(i,10, 0);
+ ZWRITE(i, 1, 0x10); /* int on all Rx chars or special condition */
+ set_vector(SCCReceiverISR, SCC_VECTOR+(i/2), 1); /* install ISR */
+ ZWRITE(i, 9, 8); /* master interrupt enable */
+ ZWRITE(i,12,TC38400&0xff); /* set 38400 baud */
+ ZWRITE(i,13,TC38400>>8);
+ ZWRITE(i,14, 3); /* start baudrate gen. */
+ /* CAUTION: If your SCC use XTAL on RTxC,
+ write 1 */
+ }
+ mcchip->vector_base = 0;
+ mcchip->gen_control = 2; /* MIEN */
+ mcchip->SCC_int_ctl = 0x13; /* SCC IEN, IPL3 */
+}
+
+/*
+ * Non-blocking char input
+ */
+
+rtems_boolean SCCGetOne(int port, char *ch)
+{
+ int retry = READRETRY;
+ while(ReceiverBufferIsEmpty(&receiverBuffer[port]))
+ if(--retry <= 0)
+ return FALSE;
+
+ ReceiverBufferRemove(&receiverBuffer[port],*ch);
+
+ if(ReceiverBufferIsNearEmpty(&receiverBuffer[port]))
+ SCCSetRTS(port);
+ return TRUE;
+}
+
+/*
+ * Blocking char input
+ */
+
+char SCCGetOneBlocked(int port)
+{
+ unsigned char tmp_char;
+
+ while (!SCCGetOne(port, &tmp_char))
+ rtems_task_wake_after(RTEMS_YIELD_PROCESSOR);
+ return tmp_char;
+}
+
+/*
+ * Non-blocking char input
+ * No longer supports XON/XOFF flow control.
+ */
+
+rtems_boolean SCCSendOne(int port, char ch)
+{
+ int retry = WRITERETRY;
+
+ if(!SCCGetCTS(port))
+ return FALSE;
+ while(!(ZREAD0(port) & TX_BUFFER_EMPTY))
+ if(--retry <= 0)
+ return FALSE;
+ ZWRITED(port, ch);
+ return TRUE;
+}
+
+
+/*
+ * Blocking char output
+ * No longer supports XON/XOFF flow control.
+ */
+
+void SCCSendOneBlocked(int port, char ch)
+{
+ while(!SCCSendOne(port, ch))
+ rtems_task_wake_after(RTEMS_YIELD_PROCESSOR);
+}
+
+/*
+ * Set parameters for transmission
+ */
+
+unsigned32 SCCSetAttributes(int port, struct termios *t)
+{
+ unsigned char wr3;
+
+ ZWRITE(port,1,0); /* Disable interrupt */
+ ZWRITE(port,3,0); /* Disable receiver */
+ /* Baud */
+ switch(t->c_cflag & CBAUD){
+ case B38400:
+ ZWRITE(port,12,TC38400&0xff);
+ ZWRITE(port,13,TC38400>>8);
+ break;
+ case B19200:
+ ZWRITE(port,12,TC19200&0xff);
+ ZWRITE(port,13,TC19200>>8);
+ break;
+ case B9600:
+ ZWRITE(port,12,TC9600&0xff);
+ ZWRITE(port,13,TC9600>>8);
+ break;
+ }
+
+ /* Code size */
+ wr5[port] &= 0x8f;
+ wr3 = 0; /* receiver control */
+ switch(t->c_cflag & CSIZE){
+ case CS8:
+ wr5[port] |= 0x60;
+ wr3 |= 0xc0;
+ break;
+ case CS7:
+ wr5[port] |= 0x20;
+ wr3 |= 0x40;
+ break;
+ }
+
+ /* Parity */
+ wr4[port] &= 0xf0;
+ if(t->c_cflag & PARENB)
+ wr4[port] |= 0x01;
+ if(!(t->c_cflag & PARODD))
+ wr4[port] |= 0x02;
+ /* ZWRITE(port,4,wr4[port]);*/
+
+ /* Stop bits */
+ /* wr4[port] = ZREAD(port,4) & 0xfc;*/
+ if(t->c_cflag & CSTOPB)
+ wr4[port] |= 0x0c;
+ else
+ wr4[port] |= 0x04;
+
+ ZWRITE(port,4,wr4[port]); /* TxRx parameters */
+ ZWRITE(port,5,wr5[port]); /* Transmission parameters */
+ ZWRITE(port,3,wr3|0x01); /* Enable receiver */
+ ZWRITE(port,1,0x10); /* Enable interrupt */
+
+ return 0;
+}
+
+/*
+ * Get parameters for transmission
+ */
+
+unsigned32 SCCGetAttributes(int port, struct termios *t)
+{
+ unsigned32 b;
+
+ t->c_cflag = 0;
+
+ /* Baud */
+ b = ZREAD(port,13);
+ b <<= 8;
+ b |= ZREAD(port,12);
+ switch(b){
+ case TC38400:
+ t->c_cflag |= B38400;
+ break;
+ case TC19200:
+ t->c_cflag |= B19200;
+ break;
+ case TC9600:
+ t->c_cflag |= B9600;
+ break;
+ }
+
+ /* Code size */
+ /* wr = ZREAD(port,5);*/
+ t->c_cflag &= ~CSIZE;
+ switch(wr5[port]&0x60){
+ case 0x60:
+ t->c_cflag |= CS8;
+ break;
+ case 0x20:
+ t->c_cflag |= CS7;
+ break;
+ }
+
+ /* Parity */
+ /* wr = ZREAD(port,4);*/
+ if(wr4[port] & 0x01)
+ t->c_cflag |= PARENB;
+ else
+ t->c_cflag &= ~PARENB;
+ if(wr4[port] & 0x02)
+ t->c_cflag &= ~PARODD;
+ else
+ t->c_cflag |= PARODD;
+
+ /* Stop bits */
+ /* wr = ZREAD(port,4);*/
+ if((wr4[port]&0xc0) == 0xc0)
+ t->c_cflag |= CSTOPB;
+ else
+ t->c_cflag &= ~CSTOPB;
+
+ return 0;
+}
+
+/***********************************************************************
+ DEVICE INDEPENDED PART
+ ***********************************************************************/
+
+#define LOCAL_ISTRIP 0x0001
+#define LOCAL_INLCR 0x0002
+#define LOCAL_IGNCR 0x0004
+#define LOCAL_ICRNL 0x0008
+#define LOCAL_IUCLC 0x0010
+#define LOCAL_OLCUC 0x0020
+#define LOCAL_ONLCR 0x0040
+#define LOCAL_OCRNL 0x0080
+#define LOCAL_ICANON 0x0100
+#define LOCAL_ECHO 0x0200
+
+/*
+ * Device initialize entry point
+ */
+
+rtems_device_driver consolex_initialize(rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg)
+{
+ rtems_status_code status;
+ char devname[16];
+ int i;
+
+ SCCInitialize();
+
+#ifdef CONSOLEPORT
+ status = rtems_io_register_name("/dev/console",major,
+ (rtems_device_minor_number) CONSOLEPORT);
+ if (status != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred(status);
+#endif
+
+ for(i = PORTFROM; i < NPORTS; i++){
+ /* Register cooked ttys */
+ sprintf(devname,"/dev/%s%02d",DEVICEPREFIX,i);
+ status = rtems_io_register_name(strdup(devname),major,
+ (rtems_device_minor_number) i);
+ if (status != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred(status);
+ /* Register raw ttys */
+ sprintf(devname,"/dev/%s%02d",RAWDEVICEPREFIX,i);
+ status = rtems_io_register_name(strdup(devname),major,
+ (rtems_device_minor_number) i+NPORTS);
+ if (status != RTEMS_SUCCESSFUL)
+ rtems_fatal_error_occurred(status);
+ }
+
+ for(i = 0; i < NPORTS; i++){
+ opencount[i] = 0;
+ }
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * Open entry point
+ */
+
+rtems_device_driver consolex_open(rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg)
+{
+ rtems_libio_open_close_args_t *openargs = (rtems_libio_open_close_args_t *) arg;
+ if(minor >= NPORTS)
+ minor -= NPORTS;
+ if(minor >= NPORTS)
+ return RTEMS_INVALID_NUMBER;
+
+ if(opencount[minor]++ == 0){
+ /* first open */
+ SCCSetDTR(minor);
+ SCCSetRTS(minor);
+ }
+ openargs->iop->data0 = LOCAL_ICRNL|LOCAL_ONLCR|LOCAL_ICANON|LOCAL_ECHO;
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * Close entry point
+ */
+
+rtems_device_driver consolex_close(rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg)
+{
+ if(minor >= NPORTS)
+ minor -= NPORTS;
+ if(minor >= NPORTS)
+ return RTEMS_INVALID_NUMBER;
+
+ if(--(opencount[minor]) == 0){
+ /* closed all */
+ SCCResetRTS(minor);
+ SCCResetDTR(minor);
+ }
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * read bytes from the serial port.
+ */
+
+rtems_device_driver consolex_read_raw(rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg)
+{
+ rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *) arg;
+ char *buffer;
+ int count;
+
+ if(minor >= NPORTS)
+ return RTEMS_INVALID_NUMBER;
+
+ buffer = rw_args->buffer;
+ count = rw_args->count;
+
+ if(rw_args->flags & LIBIO_FLAGS_NO_DELAY){
+ /* Non blocking read */
+ while(count){
+ if(!SCCGetOne(minor,buffer))
+ break;
+ buffer++;
+ count--;
+ }
+ }else{
+ /* Blocking read */
+ while(count){
+ *buffer = SCCGetOneBlocked(minor);
+ buffer++;
+ count--;
+ }
+ }
+
+ rw_args->bytes_moved = rw_args->count-count;
+ return count ? RTEMS_UNSATISFIED : RTEMS_SUCCESSFUL;
+}
+
+rtems_device_driver consolex_read(rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg)
+{
+ rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *) arg;
+ char *buffer;
+ int count;
+ unsigned32 mode;
+
+ if(minor >= NPORTS)
+ return consolex_read_raw(major,minor-NPORTS,arg);
+
+ buffer = rw_args->buffer;
+ count = rw_args->count;
+ mode = rw_args->iop->data0;
+
+ /* Cooked read */
+ while(count){
+ if(rw_args->flags & LIBIO_FLAGS_NO_DELAY){
+ /* Non blocking read */
+ if(!SCCGetOne(minor,buffer))
+ break;
+ }else{
+ /* Blocking read */
+ *buffer = SCCGetOneBlocked(minor);
+ }
+ if((mode&LOCAL_ICANON) && (*buffer == '\b')){
+ if(buffer > (char *)(rw_args->buffer)){
+ buffer--;
+ count++;
+ if(mode&LOCAL_ECHO){
+ SCCSendOneBlocked(minor,'\b');
+ SCCSendOneBlocked(minor,' ');
+ SCCSendOneBlocked(minor,'\b');
+ }
+ }
+ continue;
+ }
+ if((mode&LOCAL_IGNCR) && (*buffer == '\r'))
+ continue;
+ if((mode&LOCAL_INLCR) && (*buffer == '\n'))
+ *buffer = '\r';
+ if((mode&LOCAL_ICRNL) && (*buffer == '\r'))
+ *buffer = '\n';
+ if((mode&LOCAL_IUCLC) && isupper(*buffer))
+ *buffer = tolower(*buffer);
+ if(mode&LOCAL_ISTRIP)
+ *buffer &= 0x7f;
+ if(mode&LOCAL_ECHO){
+ /* Caution: Echo back is blocking output */
+ SCCSendOneBlocked(minor,*buffer);
+ }
+ if((mode&LOCAL_ICANON) && (*buffer == '\n')){
+ buffer++;
+ count--;
+ if(count)
+ *buffer = 0;
+ if((mode&LOCAL_ECHO)&&(mode&LOCAL_ONLCR))
+ SCCSendOneBlocked(minor,'\r');
+ break; /* finish reading */
+ }
+ buffer++;
+ count--;
+ }
+ rw_args->bytes_moved = rw_args->count-count;
+ return count ? RTEMS_UNSATISFIED : RTEMS_SUCCESSFUL;
+}
+
+/*
+ * write bytes to the serial port.
+ */
+
+rtems_device_driver consolex_write_raw(rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg)
+{
+ rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *) arg;
+ char *buffer;
+ int count;
+
+ if(minor >= NPORTS)
+ return RTEMS_INVALID_NUMBER;
+
+ buffer = rw_args->buffer;
+ count = rw_args->count;
+
+ if(rw_args->flags & LIBIO_FLAGS_NO_DELAY){
+ /* Non blocking write */
+ while(count){
+ if(!SCCSendOne(minor,*buffer))
+ break;
+ buffer++;
+ count--;
+ }
+ }else{
+ /* Blocking write */
+ while(count){
+ SCCSendOneBlocked(minor,*buffer);
+ buffer++;
+ count--;
+ }
+ }
+
+ rw_args->bytes_moved = rw_args->count-count;
+ return count ? RTEMS_UNSATISFIED : RTEMS_SUCCESSFUL;
+}
+
+rtems_device_driver consolex_write(rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg)
+{
+ rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *) arg;
+ char *buffer;
+ int count;
+ char ch;
+ unsigned32 mode;
+
+ if(minor >= NPORTS)
+ return consolex_write_raw(major,minor-NPORTS,arg);
+
+ buffer = rw_args->buffer;
+ count = rw_args->count;
+ mode = rw_args->iop->data0;
+
+ /* Cooked write */
+ while(count){
+ ch = *buffer;
+ if((mode&LOCAL_ONLCR) && (ch == '\n')){ /* Output CRLF */
+ if(rw_args->flags & LIBIO_FLAGS_NO_DELAY){
+ /* Non blocking write */
+ if(!SCCSendOne(minor,'\r'))
+ break;
+ }else{
+ SCCSendOneBlocked(minor,'\r');
+ }
+ }
+ if((mode&LOCAL_OCRNL) && (ch == '\r'))
+ ch = '\n';
+ if((mode&OLCUC) && (islower(ch)))
+ ch = toupper(ch);
+ if(rw_args->flags & LIBIO_FLAGS_NO_DELAY){
+ /* Non blocking write */
+ if(!SCCSendOne(minor,ch))
+ break;
+ }else{
+ SCCSendOneBlocked(minor,ch);
+ }
+ buffer++;
+ count--;
+ }
+
+ rw_args->bytes_moved = rw_args->count-count;
+ return count ? RTEMS_UNSATISFIED : RTEMS_SUCCESSFUL;
+}
+
+/*
+ * IO Control entry point
+ */
+
+rtems_device_driver consolex_control(rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void * arg)
+{
+ rtems_libio_ioctl_args_t *ioarg = (rtems_libio_ioctl_args_t *)arg;
+ struct termios *tm = ioarg->buffer;
+ unsigned32 *mode = &(ioarg->iop->data0);
+
+ if(minor >= NPORTS)
+ minor -= NPORTS;
+ if(minor >= NPORTS)
+ return RTEMS_INVALID_NUMBER;
+
+ switch(ioarg->command){
+ case RTEMS_IO_GET_ATTRIBUTES:
+ tm->c_iflag = tm->c_oflag = tm->c_cflag = tm->c_lflag = 0;
+ if(*mode & LOCAL_ISTRIP)
+ tm->c_iflag |= ISTRIP;
+ if(*mode & LOCAL_INLCR)
+ tm->c_iflag |= INLCR;
+ if(*mode & LOCAL_IGNCR)
+ tm->c_iflag |= IGNCR;
+ if(*mode & LOCAL_ICRNL)
+ tm->c_iflag |= ICRNL;
+ if(*mode & LOCAL_IUCLC)
+ tm->c_iflag |= IUCLC;
+ if(*mode & LOCAL_OLCUC)
+ tm->c_oflag |= OLCUC;
+ if(*mode & LOCAL_ONLCR)
+ tm->c_oflag |= ONLCR;
+ if(*mode & LOCAL_OCRNL)
+ tm->c_oflag |= OCRNL;
+ if(*mode & LOCAL_ICANON)
+ tm->c_lflag |= ICANON;
+ if(*mode & LOCAL_ECHO)
+ tm->c_lflag |= ECHO;
+ ioarg->ioctl_return = SCCGetAttributes(minor,tm);
+ break;
+ case RTEMS_IO_SET_ATTRIBUTES:
+ *mode = 0;
+ if(tm->c_iflag & ISTRIP)
+ *mode |= LOCAL_ISTRIP;
+ if(tm->c_iflag & INLCR)
+ *mode |= LOCAL_INLCR;
+ if(tm->c_iflag & IGNCR)
+ *mode |= LOCAL_IGNCR;
+ if(tm->c_iflag & ICRNL)
+ *mode |= LOCAL_ICRNL;
+ if(tm->c_iflag & IUCLC)
+ *mode |= LOCAL_IUCLC;
+ if(tm->c_oflag & OLCUC)
+ *mode |= LOCAL_OLCUC;
+ if(tm->c_oflag & ONLCR)
+ *mode |= LOCAL_ONLCR;
+ if(tm->c_oflag & OCRNL)
+ *mode |= LOCAL_OCRNL;
+ if(tm->c_lflag & ICANON)
+ *mode |= LOCAL_ICANON;
+ if(tm->c_lflag & ECHO)
+ *mode |= LOCAL_ECHO;
+ ioarg->ioctl_return = SCCSetAttributes(minor,tm);
+ break;
+ default:
+ return RTEMS_NOT_DEFINED;
+ }
+
+ return RTEMS_SUCCESSFUL;
+}