summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp/m68k/mvme162/consolex/consolex.c
diff options
context:
space:
mode:
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;
+}