Changeset 118a812 in rtems


Ignore:
Timestamp:
Oct 23, 1997, 1:13:46 PM (23 years ago)
Author:
Joel Sherrill <joel.sherrill@…>
Branches:
4.10, 4.11, 4.8, 4.9, 5, master
Children:
3ee825e8
Parents:
3dbcece
Message:

New termios.c from Eric Norum.

Added new entry point to add in per physical port resource requirements.

Files:
7 edited

Legend:

Unmodified
Added
Removed
  • c/src/exec/libcsupport/include/rtems/libio.h

    r3dbcece r118a812  
    148148rtems_status_code rtems_termios_ioctl (void *arg);
    149149void rtems_termios_enqueue_raw_characters (void *ttyp, char *buf, int len);
     150void rtems_termios_reserve_resources(
     151  rtems_configuration_table *configuration,
     152  rtems_unsigned32           number_of_devices
     153);
    150154
    151155#endif /* _RTEMS_LIBIO_H */
  • c/src/exec/libcsupport/src/termios.c

    r3dbcece r118a812  
    2424#include <termios.h>
    2525#include <unistd.h>
    26 #include <ringbuf.h>
    2726
    2827/*
    2928 * The size of the cooked buffer
    3029 */
    31 #define CBUFSIZE  256
     30#define CBUFSIZE        256
     31
     32/*
     33 * The size of the raw input message queue
     34 */
     35#define RAW_BUFFER_SIZE 128
    3236
    3337/*
     
    3640 */
    3741struct rtems_termios_tty {
    38   /*
    39    * Linked-list of active TERMIOS devices
    40    */
    41   struct rtems_termios_tty  *forw;
    42   struct rtems_termios_tty  *back;
    43 
    44   /*
    45    * How many times has this device been opened
    46    */
    47   int   refcount;
    48 
    49   /*
    50    * This device
    51    */
    52   rtems_device_major_number major;
    53   rtems_device_major_number minor;
    54 
    55   /*
    56    * Mutual-exclusion semaphores
    57    */
    58   rtems_id  isem;
    59   rtems_id  osem;
    60 
    61   /*
    62    * The canonical (cooked) character buffer
    63    */
    64   char    cbuf[CBUFSIZE];
    65   int   ccount;
    66   int   cindex;
    67 
    68   /*
    69    * Keep track of cursor (printhead) position
    70    */
    71   int   column;
    72   int   read_start_column;
    73 
    74   /*
    75    * The ioctl settings
    76    */
    77   struct termios  termios;
    78   rtems_interval  vtimeTicks;
    79 
    80   /*
    81    * Raw character buffer
    82    */
    83   rtems_id      rawInputSem;
    84   Ring_buffer_t rawInputBuffer;
    85 
    86   rtems_unsigned32  rawMessageOptions;
    87   rtems_interval  rawMessageTimeout;
    88   rtems_interval  rawMessageFirstTimeout;
    89 
    90   /*
    91    * Callbacks to device-specific routines
    92    */
    93   int   (*lastClose)(int major, int minor, void *arg);
    94   int   (*read)(int minor, char *buf );
    95   int   (*write)(int minor, char *buf, int len);
     42        /*
     43         * Linked-list of active TERMIOS devices
     44         */
     45        struct rtems_termios_tty        *forw;
     46        struct rtems_termios_tty        *back;
     47
     48        /*
     49         * How many times has this device been opened
     50         */
     51        int             refcount;
     52
     53        /*
     54         * This device
     55         */
     56        rtems_device_major_number       major;
     57        rtems_device_major_number       minor;
     58
     59        /*
     60         * Mutual-exclusion semaphores
     61         */
     62        rtems_id        isem;
     63        rtems_id        osem;
     64
     65        /*
     66         * The canonical (cooked) character buffer
     67         */
     68        char            cbuf[CBUFSIZE];
     69        int             ccount;
     70        int             cindex;
     71
     72        /*
     73         * Keep track of cursor (printhead) position
     74         */
     75        int             column;
     76        int             read_start_column;
     77
     78        /*
     79         * The ioctl settings
     80         */
     81        struct termios  termios;
     82        rtems_interval  vtimeTicks;
     83
     84        /*
     85         * Raw character buffer
     86         */
     87        volatile char           rawBuf[RAW_BUFFER_SIZE];
     88        volatile unsigned int   rawBufHead;
     89        volatile unsigned int   rawBufTail;
     90        rtems_id                rawBufSemaphore;
     91        rtems_unsigned32        rawBufSemaphoreOptions;
     92        rtems_interval          rawBufSemaphoreTimeout;
     93        rtems_interval          rawBufSemaphoreFirstTimeout;
     94        unsigned int            rawBufDropped;  /* Statistics */
     95
     96        /*
     97         * Callbacks to device-specific routines
     98         */
     99        int             (*lastClose)(int major, int minor, void *arg);
     100        int             (*read)(int minor, char *buf);
     101        int             (*write)(int minor, char *buf, int len);
    96102};
    97103static struct rtems_termios_tty *ttyHead, *ttyTail;
     
    101107rtems_termios_initialize (void)
    102108{
    103   rtems_status_code sc;
    104 
    105   /*
    106   * Create the mutex semaphore for the tty list
    107   */
    108   if (!ttyMutex) {
    109     sc = rtems_semaphore_create (
    110       rtems_build_name ('T', 'R', 'm', 'i'),
    111       1,
    112       RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
    113       RTEMS_NO_PRIORITY,
    114       &ttyMutex);
    115     if (sc != RTEMS_SUCCESSFUL)
    116       rtems_fatal_error_occurred (sc);
    117   }
    118 }
    119  
     109        rtems_status_code sc;
     110
     111        /*
     112        * Create the mutex semaphore for the tty list
     113        */
     114        if (!ttyMutex) {
     115                sc = rtems_semaphore_create (
     116                        rtems_build_name ('T', 'R', 'm', 'i'),
     117                        1,
     118                        RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
     119                        RTEMS_NO_PRIORITY,
     120                        &ttyMutex);
     121                if (sc != RTEMS_SUCCESSFUL)
     122                        rtems_fatal_error_occurred (sc);
     123        }
     124}
     125       
    120126/*
    121127 * Open a termios device
     
    128134  int                      (*deviceFirstOpen)(int major, int minor, void *arg),
    129135  int                      (*deviceLastClose)(int major, int minor, void *arg),
    130   int                      (*deviceRead)(int minor, char *buf/*, int len*/),
     136  int                      (*deviceRead)(int minor, char *buf),
    131137  int                      (*deviceWrite)(int minor, char *buf, int len)
    132138  )
    133139{
    134   rtems_status_code sc;
    135   rtems_libio_open_close_args_t *args = arg;
    136   struct rtems_termios_tty *tty;
    137 
    138   /*
    139    * See if the device has already been opened
    140    */
    141   sc = rtems_semaphore_obtain (ttyMutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
    142   if (sc != RTEMS_SUCCESSFUL)
    143     return sc;
    144   for (tty = ttyHead ; tty != NULL ; tty = tty->forw) {
    145     if ((tty->major == major) && (tty->minor == minor))
    146       break;
    147   }
    148   if (tty == NULL) {
    149     static char c = 'a';
    150 
    151     /*
    152      * Create a new device
    153      */
    154     tty = malloc (sizeof (struct rtems_termios_tty));
    155     if (tty == NULL) {
    156       rtems_semaphore_release (ttyMutex);
    157       return RTEMS_NO_MEMORY;
    158     }
    159     tty->forw = ttyHead;
    160     ttyHead = tty;
    161     tty->back = NULL;
    162     if (ttyTail == NULL)
    163       ttyTail = tty;
    164 
    165     /*
    166      * Set up mutex semaphores
    167      */
    168     sc = rtems_semaphore_create (
    169       rtems_build_name ('T', 'R', 'i', c),
    170       1,
    171       RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
    172       RTEMS_NO_PRIORITY,
    173       &tty->isem);
    174     if (sc != RTEMS_SUCCESSFUL)
    175       rtems_fatal_error_occurred (sc);
    176     sc = rtems_semaphore_create (
    177       rtems_build_name ('T', 'R', 'o', c),
    178       1,
    179       RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
    180       RTEMS_NO_PRIORITY,
    181       &tty->osem);
    182     if (sc != RTEMS_SUCCESSFUL)
    183       rtems_fatal_error_occurred (sc);
    184 
    185     /*
    186      * Set callbacks
    187      */
    188     tty->write = deviceWrite;
    189     tty->lastClose = deviceLastClose;
    190     if ((tty->read = deviceRead) == NULL) {
    191       sc = rtems_semaphore_create (
    192         rtems_build_name ('T', 'R', 'r', c),
    193         0,
    194         RTEMS_COUNTING_SEMAPHORE | RTEMS_FIFO | RTEMS_LOCAL,
    195         RTEMS_NO_PRIORITY,
    196         &tty->rawInputSem);
    197       if (sc != RTEMS_SUCCESSFUL)
    198         rtems_fatal_error_occurred (sc);
    199     }
    200 
    201     /*
    202      * Initialize variables
    203      */
    204     tty->column = 0;
    205     tty->cindex = tty->ccount = 0;
    206 
    207     /*
    208      * Set default parameters
    209      */
    210     tty->termios.c_iflag = BRKINT | ICRNL | IXON | IMAXBEL;
    211     tty->termios.c_oflag = OPOST | ONLCR | XTABS;
    212     tty->termios.c_cflag = B9600 | CS8 | CREAD;
    213     tty->termios.c_lflag = ISIG | ICANON | IEXTEN | ECHO | ECHOK | ECHOE | ECHOCTL;
    214     tty->termios.c_cc[VINTR] = '\003';
    215     tty->termios.c_cc[VQUIT] = '\034';
    216     tty->termios.c_cc[VERASE] = '\177';
    217     tty->termios.c_cc[VKILL] = '\025';
    218     tty->termios.c_cc[VEOF] = '\004';
    219     tty->termios.c_cc[VEOL] = '\000';
    220     tty->termios.c_cc[VEOL2] = '\000';
    221     tty->termios.c_cc[VSTART] = '\021';
    222     tty->termios.c_cc[VSTOP] = '\023';
    223     tty->termios.c_cc[VSUSP] = '\032';
    224     tty->termios.c_cc[VREPRINT] = '\022';
    225     tty->termios.c_cc[VDISCARD] = '\017';
    226     tty->termios.c_cc[VWERASE] = '\027';
    227     tty->termios.c_cc[VLNEXT] = '\026';
    228 
    229     /*
    230      * Device-specific open
    231      */
    232     if (deviceFirstOpen)
    233       (*deviceFirstOpen) (major, minor, arg);
    234 
    235     /*
    236      * Bump name characer
    237      */
    238     if (c++ == 'z')
    239       c = 'a';
    240   }
    241   tty->refcount++;
    242   args->iop->data1 = tty;
    243   rtems_semaphore_release (ttyMutex);
    244   return RTEMS_SUCCESSFUL;
     140        rtems_status_code sc;
     141        rtems_libio_open_close_args_t *args = arg;
     142        struct rtems_termios_tty *tty;
     143
     144        /*
     145         * See if the device has already been opened
     146         */
     147        sc = rtems_semaphore_obtain (ttyMutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
     148        if (sc != RTEMS_SUCCESSFUL)
     149                return sc;
     150        for (tty = ttyHead ; tty != NULL ; tty = tty->forw) {
     151                if ((tty->major == major) && (tty->minor == minor))
     152                        break;
     153        }
     154        if (tty == NULL) {
     155                static char c = 'a';
     156
     157                /*
     158                 * Create a new device
     159                 */
     160                tty = malloc (sizeof (struct rtems_termios_tty));
     161                if (tty == NULL) {
     162                        rtems_semaphore_release (ttyMutex);
     163                        return RTEMS_NO_MEMORY;
     164                }
     165                tty->forw = ttyHead;
     166                ttyHead = tty;
     167                tty->back = NULL;
     168                if (ttyTail == NULL)
     169                        ttyTail = tty;
     170
     171                /*
     172                 * Set up mutex semaphores
     173                 */
     174                sc = rtems_semaphore_create (
     175                        rtems_build_name ('T', 'R', 'i', c),
     176                        1,
     177                        RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
     178                        RTEMS_NO_PRIORITY,
     179                        &tty->isem);
     180                if (sc != RTEMS_SUCCESSFUL)
     181                        rtems_fatal_error_occurred (sc);
     182                sc = rtems_semaphore_create (
     183                        rtems_build_name ('T', 'R', 'o', c),
     184                        1,
     185                        RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
     186                        RTEMS_NO_PRIORITY,
     187                        &tty->osem);
     188                if (sc != RTEMS_SUCCESSFUL)
     189                        rtems_fatal_error_occurred (sc);
     190
     191                /*
     192                 * Set callbacks
     193                 */
     194                tty->write = deviceWrite;
     195                tty->lastClose = deviceLastClose;
     196                if ((tty->read = deviceRead) == NULL) {
     197                        sc = rtems_semaphore_create (
     198                                rtems_build_name ('T', 'R', 'r', c),
     199                                0,
     200                                RTEMS_COUNTING_SEMAPHORE | RTEMS_PRIORITY,
     201                                RTEMS_NO_PRIORITY,
     202                                &tty->rawBufSemaphore);
     203                        if (sc != RTEMS_SUCCESSFUL)
     204                                rtems_fatal_error_occurred (sc);
     205                        tty->rawBufHead = 0;
     206                        tty->rawBufTail = 0;
     207                }
     208
     209                /*
     210                 * Initialize variables
     211                 */
     212                tty->column = 0;
     213                tty->cindex = tty->ccount = 0;
     214
     215                /*
     216                 * Set default parameters
     217                 */
     218                tty->termios.c_iflag = BRKINT | ICRNL | IXON | IMAXBEL;
     219                tty->termios.c_oflag = OPOST | ONLCR | XTABS;
     220                tty->termios.c_cflag = B9600 | CS8 | CREAD;
     221                tty->termios.c_lflag = ISIG | ICANON | IEXTEN | ECHO | ECHOK | ECHOE | ECHOCTL;
     222                tty->termios.c_cc[VINTR] = '\003';
     223                tty->termios.c_cc[VQUIT] = '\034';
     224                tty->termios.c_cc[VERASE] = '\177';
     225                tty->termios.c_cc[VKILL] = '\025';
     226                tty->termios.c_cc[VEOF] = '\004';
     227                tty->termios.c_cc[VEOL] = '\000';
     228                tty->termios.c_cc[VEOL2] = '\000';
     229                tty->termios.c_cc[VSTART] = '\021';
     230                tty->termios.c_cc[VSTOP] = '\023';
     231                tty->termios.c_cc[VSUSP] = '\032';
     232                tty->termios.c_cc[VREPRINT] = '\022';
     233                tty->termios.c_cc[VDISCARD] = '\017';
     234                tty->termios.c_cc[VWERASE] = '\027';
     235                tty->termios.c_cc[VLNEXT] = '\026';
     236
     237                /*
     238                 * Device-specific open
     239                 */
     240                if (deviceFirstOpen)
     241                        (*deviceFirstOpen) (major, minor, arg);
     242
     243                /*
     244                 * Bump name characer
     245                 */
     246                if (c++ == 'z')
     247                        c = 'a';
     248        }
     249        tty->refcount++;
     250        args->iop->data1 = tty;
     251        rtems_semaphore_release (ttyMutex);
     252        return RTEMS_SUCCESSFUL;
    245253}
    246254
     
    248256rtems_termios_close (void *arg)
    249257{
    250   rtems_libio_open_close_args_t *args = arg;
    251   struct rtems_termios_tty *tty = args->iop->data1;
    252   rtems_status_code sc;
    253 
    254   sc = rtems_semaphore_obtain (ttyMutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
    255   if (sc != RTEMS_SUCCESSFUL)
    256     rtems_fatal_error_occurred (sc);
    257   if (--tty->refcount == 0) {
    258     if (tty->lastClose)
    259       (*tty->lastClose) (tty->major, tty->minor, arg);
    260     if (tty->forw == NULL)
    261       ttyTail = tty->back;
    262     else
    263       tty->forw->back = tty->back;
    264     if (tty->back == NULL)
    265       ttyHead = tty->forw;
    266     else
    267       tty->back->forw = tty->forw;
    268     rtems_semaphore_delete (tty->isem);
    269     rtems_semaphore_delete (tty->osem);
    270     if (tty->read == NULL)
    271       rtems_semaphore_delete (tty->rawInputSem);
    272     free (tty);
    273   }
    274   rtems_semaphore_release (ttyMutex);
    275   return RTEMS_SUCCESSFUL;
     258        rtems_libio_open_close_args_t *args = arg;
     259        struct rtems_termios_tty *tty = args->iop->data1;
     260        rtems_status_code sc;
     261
     262        sc = rtems_semaphore_obtain (ttyMutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
     263        if (sc != RTEMS_SUCCESSFUL)
     264                rtems_fatal_error_occurred (sc);
     265        if (--tty->refcount == 0) {
     266                if (tty->lastClose)
     267                        (*tty->lastClose) (tty->major, tty->minor, arg);
     268                if (tty->forw == NULL)
     269                        ttyTail = tty->back;
     270                else
     271                        tty->forw->back = tty->back;
     272                if (tty->back == NULL)
     273                        ttyHead = tty->forw;
     274                else
     275                        tty->back->forw = tty->forw;
     276                rtems_semaphore_delete (tty->isem);
     277                rtems_semaphore_delete (tty->osem);
     278                if (tty->read == NULL)
     279                        rtems_semaphore_delete (tty->rawBufSemaphore);
     280                free (tty);
     281        }
     282        rtems_semaphore_release (ttyMutex);
     283        return RTEMS_SUCCESSFUL;
    276284}
    277285
     
    279287rtems_termios_ioctl (void *arg)
    280288{
    281   rtems_libio_ioctl_args_t *args = arg;
    282   struct rtems_termios_tty *tty = args->iop->data1;
    283   rtems_status_code sc;
    284 
    285   sc = rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
    286   if (sc != RTEMS_SUCCESSFUL)
    287     return sc;
    288   switch (args->command) {
    289   default:
    290     sc = RTEMS_INVALID_NUMBER;
    291     break;
    292 
    293   case RTEMS_IO_GET_ATTRIBUTES:
    294     *(struct termios *)args->buffer = tty->termios;
    295     break;
    296 
    297   case RTEMS_IO_SET_ATTRIBUTES:
    298     tty->termios = *(struct termios *)args->buffer;
    299     if (tty->termios.c_lflag & ICANON) {
    300       tty->rawMessageOptions = RTEMS_WAIT;
    301       tty->rawMessageTimeout = RTEMS_NO_TIMEOUT;
    302       tty->rawMessageFirstTimeout = RTEMS_NO_TIMEOUT;
    303     }
    304     else {
    305       rtems_interval ticksPerSecond;
    306       rtems_clock_get (RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticksPerSecond);
    307       tty->vtimeTicks = tty->termios.c_cc[VTIME] * ticksPerSecond / 10;
    308       if (tty->termios.c_cc[VTIME]) {
    309         tty->rawMessageOptions = RTEMS_WAIT;
    310         tty->rawMessageTimeout = tty->vtimeTicks;
    311         if (tty->termios.c_cc[VMIN])
    312           tty->rawMessageFirstTimeout = RTEMS_NO_TIMEOUT;
    313         else
    314           tty->rawMessageFirstTimeout = tty->vtimeTicks;
    315       }
    316       else {
    317         if (tty->termios.c_cc[VMIN]) {
    318           tty->rawMessageOptions = RTEMS_WAIT;
    319           tty->rawMessageTimeout = RTEMS_NO_TIMEOUT;
    320           tty->rawMessageFirstTimeout = RTEMS_NO_TIMEOUT;
    321         }
    322         else {
    323           tty->rawMessageOptions = RTEMS_NO_WAIT;
    324         }
    325       }
    326     }
    327     break;
    328   }
    329   rtems_semaphore_release (tty->osem);
    330   return sc;
     289        rtems_libio_ioctl_args_t *args = arg;
     290        struct rtems_termios_tty *tty = args->iop->data1;
     291        rtems_status_code sc;
     292
     293        sc = rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
     294        if (sc != RTEMS_SUCCESSFUL)
     295                return sc;
     296        switch (args->command) {
     297        default:
     298                sc = RTEMS_INVALID_NUMBER;
     299                break;
     300
     301        case RTEMS_IO_GET_ATTRIBUTES:
     302                *(struct termios *)args->buffer = tty->termios;
     303                break;
     304
     305        case RTEMS_IO_SET_ATTRIBUTES:
     306                tty->termios = *(struct termios *)args->buffer;
     307                if (tty->termios.c_lflag & ICANON) {
     308                        tty->rawBufSemaphoreOptions = RTEMS_WAIT;
     309                        tty->rawBufSemaphoreTimeout = RTEMS_NO_TIMEOUT;
     310                        tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
     311                }
     312                else {
     313                        rtems_interval ticksPerSecond;
     314                        rtems_clock_get (RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticksPerSecond);
     315                        tty->vtimeTicks = tty->termios.c_cc[VTIME] * ticksPerSecond / 10;
     316                        if (tty->termios.c_cc[VTIME]) {
     317                                tty->rawBufSemaphoreOptions = RTEMS_WAIT;
     318                                tty->rawBufSemap`oreTimeout = tty->vtimeTicks;
     319                                if (tty->termios.c_cc[VMIN])
     320                                        tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
     321                                else
     322                                        tty->rawBufSemaphoreFirstTimeout = tty->vtimeTicks;
     323                        }
     324                        else {
     325                                if (tty->termios.c_cc[VMIN]) {
     326                                        tty->rawBufSemaphoreOptions = RTEMS_WAIT;
     327                                        tty->rawBufSemaphoreTimeout = RTEMS_NO_TIMEOUT;
     328                                        tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
     329                                }
     330                                else {
     331                                        tty->rawBufSemaphoreOptions = RTEMS_NO_WAIT;
     332                                }
     333                        }
     334                }
     335                break;
     336        }
     337        rtems_semaphore_release (tty->osem);
     338        return sc;
    331339}
    332340
     
    337345oproc (unsigned char c, struct rtems_termios_tty *tty)
    338346{
    339   int i;
    340 
    341   if (tty->termios.c_oflag & OPOST) {
    342     switch (c) {
    343     case '\n':
    344       if (tty->termios.c_oflag & ONLRET)
    345         tty->column = 0;
    346       if (tty->termios.c_oflag & ONLCR) {
    347         (*tty->write)(tty->minor, "\r", 1);
    348         tty->column = 0;
    349       }
    350       break;
    351 
    352     case '\r':
    353       if ((tty->termios.c_oflag & ONOCR) && (tty->column == 0))
    354         return;
    355       if (tty->termios.c_oflag & OCRNL) {
    356         c = '\n';
    357         if (tty->termios.c_oflag & ONLRET)
    358           tty->column = 0;
    359         break;
    360       }
    361       tty->column = 0;
    362       break;
    363 
    364     case '\t':
    365       i = 8 - (tty->column & 7);
    366       if ((tty->termios.c_oflag & TABDLY) == XTABS) {
    367         tty->column += i;
    368         (*tty->write)(tty->minor,  "        ",  i);
    369         return;
    370       }
    371       tty->column += i;
    372       break;
    373 
    374     case '\b':
    375       if (tty->column > 0)
    376         tty->column--;
    377       break;
    378 
    379     default:
    380       if (tty->termios.c_oflag & OLCUC)
    381         c = toupper(c);
    382       if (!iscntrl(c))
    383         tty->column++;
    384       break;
    385     }
    386   }
    387   (*tty->write)(tty->minor, &c, 1);
     347        int     i;
     348
     349        if (tty->termios.c_oflag & OPOST) {
     350                switch (c) {
     351                case '\n':
     352                        if (tty->termios.c_oflag & ONLRET)
     353                                tty->column = 0;
     354                        if (tty->termios.c_oflag & ONLCR) {
     355                                (*tty->write)(tty->minor, "\r", 1);
     356                                tty->column = 0;
     357                        }
     358                        break;
     359
     360                case '\r':
     361                        if ((tty->termios.c_oflag & ONOCR) && (tty->column == 0))
     362                                return;
     363                        if (tty->termios.c_oflag & OCRNL) {
     364                                c = '\n';
     365                                if (tty->termios.c_oflag & ONLRET)
     366                                        tty->column = 0;
     367                                break;
     368                        }
     369                        tty->column = 0;
     370                        break;
     371
     372                case '\t':
     373                        i = 8 - (tty->column & 7);
     374                        if ((tty->termios.c_oflag & TABDLY) == XTABS) {
     375                                tty->column += i;
     376                                (*tty->write)(tty->minor,  "        ",  i);
     377                                return;
     378                        }
     379                        tty->column += i;
     380                        break;
     381
     382                case '\b':
     383                        if (tty->column > 0)
     384                                tty->column--;
     385                        break;
     386
     387                default:
     388                        if (tty->termios.c_oflag & OLCUC)
     389                                c = toupper(c);
     390                        if (!iscntrl(c))
     391                                tty->column++;
     392                        break;
     393                }
     394        }
     395        (*tty->write)(tty->minor, &c, 1);
    388396}
    389397
     
    391399rtems_termios_write (void *arg)
    392400{
    393   rtems_libio_rw_args_t *args = arg;
    394   struct rtems_termios_tty *tty = args->iop->data1;
    395   rtems_status_code sc;
    396 
    397   sc = rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
    398   if (sc != RTEMS_SUCCESSFUL)
    399     return sc;
    400   if (tty->termios.c_oflag & OPOST) {
    401     unsigned32 count = args->count;
    402     unsigned8 *buffer = args->buffer;
    403     while (count--)
    404       oproc (*buffer++, tty);
    405     args->bytes_moved = args->count;
    406   }
    407   else {
    408     if ((*tty->write)(tty->minor, args->buffer, args->count) < 0)
    409       sc = RTEMS_UNSATISFIED;
    410     else
    411       args->bytes_moved = args->count;
    412   }
    413   rtems_semaphore_release (tty->osem);
    414   return sc;
     401        rtems_libio_rw_args_t *args = arg;
     402        struct rtems_termios_tty *tty = args->iop->data1;
     403        rtems_status_code sc;
     404
     405        sc = rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
     406        if (sc != RTEMS_SUCCESSFUL)
     407                return sc;
     408        if (tty->termios.c_oflag & OPOST) {
     409                unsigned32 count = args->count;
     410                unsigned8 *buffer = args->buffer;
     411                while (count--)
     412                        oproc (*buffer++, tty);
     413                args->bytes_moved = args->count;
     414        }
     415        else {
     416                if ((*tty->write)(tty->minor, args->buffer, args->count) < 0)
     417                        sc = RTEMS_UNSATISFIED;
     418                else
     419                        args->bytes_moved = args->count;
     420        }
     421        rtems_semaphore_release (tty->osem);
     422        return sc;
    415423}
    416424
     
    421429echo (unsigned char c, struct rtems_termios_tty *tty)
    422430{
    423   if ((tty->termios.c_lflag & ECHOCTL) && iscntrl(c) && (c != '\t') && (c != '\n')) {
    424     char echobuf[2];
    425 
    426     echobuf[0] = '^';
    427     echobuf[1] = c ^ 0x40;
    428     (*tty->write)(tty->minor, echobuf, 2);
    429     tty->column += 2;
    430   }
    431   else {
    432     oproc (c, tty);
    433   }
     431        if ((tty->termios.c_lflag & ECHOCTL) && iscntrl(c) && (c != '\t') && (c != '\n')) {
     432                char echobuf[2];
     433
     434                echobuf[0] = '^';
     435                echobuf[1] = c ^ 0x40;
     436                (*tty->write)(tty->minor, echobuf, 2);
     437                tty->column += 2;
     438        }
     439        else {
     440                oproc (c, tty);
     441        }
    434442}
    435443
     
    442450erase (struct rtems_termios_tty *tty, int lineFlag)
    443451{
    444   if (tty->ccount == 0)
    445     return;
    446   if (lineFlag) {
    447     if (!(tty->termios.c_lflag & ECHO)) {
    448       tty->ccount = 0;
    449       return;
    450     }
    451     if (!(tty->termios.c_lflag & ECHOE)) {
    452       tty->ccount = 0;
    453       echo (tty->termios.c_cc[VKILL], tty);
    454       if (tty->termios.c_lflag & ECHOK)
    455         echo ('\n', tty);
    456       return;
    457     }
    458   }
    459   while (tty->ccount) {
    460     unsigned char c = tty->cbuf[--tty->ccount];
    461 
    462     if (tty->termios.c_lflag & ECHO) {
    463       if (!lineFlag && !(tty->termios.c_lflag & ECHOE)) {
    464         echo (tty->termios.c_cc[VERASE], tty);
    465       }
    466       else if (c == '\t') {
    467         int col = tty->read_start_column;
    468         int i = 0;
    469 
    470         /*
    471         * Find the character before the tab
    472         */
    473         while (i != tty->ccount) {
    474           c = tty->cbuf[i++];
    475           if (c == '\t') {
    476             col = (col | 7) + 1;
    477           }
    478           else if (iscntrl (c)) {
    479             if (tty->termios.c_lflag & ECHOCTL)
    480               col += 2;
    481           }
    482           else {
    483             col++;
    484           }
    485         }
    486 
    487         /*
    488         * Back up over the tab
    489         */
    490         while (tty->column > col) {
    491           (*tty->write)(tty->minor, "\b", 1);
    492           tty->column--;
    493         }
    494       }
    495       else {
    496         if (iscntrl (c) && (tty->termios.c_lflag & ECHOCTL)) {
    497           (*tty->write)(tty->minor, "\b \b", 3);
    498           if (tty->column)
    499             tty->column--;
    500         }
    501         if (!iscntrl (c) || (tty->termios.c_lflag & ECHOCTL)) {
    502           (*tty->write)(tty->minor, "\b \b", 3);
    503           if (tty->column)
    504             tty->column--;
    505         }
    506       }
    507     }
    508     if (!lineFlag)
    509       break;
    510   }
     452        if (tty->ccount == 0)
     453                return;
     454        if (lineFlag) {
     455                if (!(tty->termios.c_lflag & ECHO)) {
     456                        tty->ccount = 0;
     457                        return;
     458                }
     459                if (!(tty->termios.c_lflag & ECHOE)) {
     460                        tty->ccount = 0;
     461                        echo (tty->termios.c_cc[VKILL], tty);
     462                        if (tty->termios.c_lflag & ECHOK)
     463                                echo ('\n', tty);
     464                        return;
     465                }
     466        }
     467        while (tty->ccount) {
     468                unsigned char c = tty->cbuf[--tty->ccount];
     469
     470                if (tty->termios.c_lflag & ECHO) {
     471                        if (!lineFlag && !(tty->termios.c_lflag & ECHOE)) {
     472                                echo (tty->termios.c_cc[VERASE], tty);
     473                        }
     474                        else if (c == '\t') {
     475                                int col = tty->read_start_column;
     476                                int i = 0;
     477
     478                                /*
     479                                * Find the character before the tab
     480                                */
     481                                while (i != tty->ccount) {
     482                                        c = tty->cbuf[i++];
     483                                        if (c == '\t') {
     484                                                col = (col | 7) + 1;
     485                                        }
     486                                        else if (iscntrl (c)) {
     487                                                if (tty->termios.c_lflag & ECHOCTL)
     488                                                        col += 2;
     489                                        }
     490                                        else {
     491                                                col++;
     492                                        }
     493                                }
     494
     495                                /*
     496                                * Back up over the tab
     497                                */
     498                                while (tty->column > col) {
     499                                        (*tty->write)(tty->minor, "\b", 1);
     500                                        tty->column--;
     501                                }
     502                        }
     503                        else {
     504                                if (iscntrl (c) && (tty->termios.c_lflag & ECHOCTL)) {
     505                                        (*tty->write)(tty->minor, "\b \b", 3);
     506                                        if (tty->column)
     507                                                tty->column--;
     508                                }
     509                                if (!iscntrl (c) || (tty->termios.c_lflag & ECHOCTL)) {
     510                                        (*tty->write)(tty->minor, "\b \b", 3);
     511                                        if (tty->column)
     512                                                tty->column--;
     513                                }
     514                        }
     515                }
     516                if (!lineFlag)
     517                        break;
     518        }
    511519}
    512520
     
    517525iproc (unsigned char c, struct rtems_termios_tty *tty)
    518526{
    519   if (tty->termios.c_iflag & ISTRIP)
    520     c &= 0x7f;
    521   if (tty->termios.c_iflag & IUCLC)
    522     c = tolower (c);
    523   if (c == '\r') {
    524     if (tty->termios.c_iflag & IGNCR)
    525       return 0;
    526     if (tty->termios.c_iflag & ICRNL)
    527       c = '\n';
    528   }
    529   else if ((c == '\n') && (tty->termios.c_iflag & INLCR)) {
    530     c = '\r';
    531   }
    532   if ((c != '\0') && (tty->termios.c_lflag & ICANON)) {
    533     if (c == tty->termios.c_cc[VERASE]) {
    534       erase (tty, 0);
    535       return 0;
    536     }
    537     else if (c == tty->termios.c_cc[VKILL]) {
    538       erase (tty, 1);
    539       return 0;
    540     }
    541     else if (c == tty->termios.c_cc[VEOF]) {
    542       return 1;
    543     }
    544     else if (c == '\n') {
    545       if (tty->termios.c_lflag & (ECHO | ECHONL))
    546         echo (c, tty);
    547       tty->cbuf[tty->ccount++] = c;
    548       return 1;
    549     }
    550     else if ((c == tty->termios.c_cc[VEOL])
    551           || (c == tty->termios.c_cc[VEOL2])) {
    552       if (tty->termios.c_lflag & ECHO)
    553         echo (c, tty);
    554       tty->cbuf[tty->ccount++] = c;
    555       return 1;
    556     }
    557   }
    558 
    559   /*
    560   * FIXME: Should do IMAXBEL handling somehow
    561   */
    562   if (tty->ccount < (CBUFSIZE-1)) {
    563     if (tty->termios.c_lflag & ECHO)
    564       echo (c, tty);
    565     tty->cbuf[tty->ccount++] = c;
    566   }
    567   return 0;
     527        if (tty->termios.c_iflag & ISTRIP)
     528                c &= 0x7f;
     529        if (tty->termios.c_iflag & IUCLC)
     530                c = tolower (c);
     531        if (c == '\r') {
     532                if (tty->termios.c_iflag & IGNCR)
     533                        return 0;
     534                if (tty->termios.c_iflag & ICRNL)
     535                        c = '\n';
     536        }
     537        else if ((c == '\n') && (tty->termios.c_iflag & INLCR)) {
     538                c = '\r';
     539        }
     540        if ((c != '\0') && (tty->termios.c_lflag & ICANON)) {
     541                if (c == tty->termios.c_cc[VERASE]) {
     542                        erase (tty, 0);
     543                        return 0;
     544                }
     545                else if (c == tty->termios.c_cc[VKILL]) {
     546                        erase (tty, 1);
     547                        return 0;
     548                }
     549                else if (c == tty->termios.c_cc[VEOF]) {
     550                        return 1;
     551                }
     552                else if (c == '\n') {
     553                        if (tty->termios.c_lflag & (ECHO | ECHONL))
     554                                echo (c, tty);
     555                        tty->cbuf[tty->ccount++] = c;
     556                        return 1;
     557                }
     558                else if ((c == tty->termios.c_cc[VEOL])
     559                      || (c == tty->termios.c_cc[VEOL2])) {
     560                        if (tty->termios.c_lflag & ECHO)
     561                                echo (c, tty);
     562                        tty->cbuf[tty->ccount++] = c;
     563                        return 1;
     564                }
     565        }
     566
     567        /*
     568        * FIXME: Should do IMAXBEL handling somehow
     569        */
     570        if (tty->ccount < (CBUFSIZE-1)) {
     571                if (tty->termios.c_lflag & ECHO)
     572                        echo (c, tty);
     573                tty->cbuf[tty->ccount++] = c;
     574        }
     575        return 0;
    568576}
    569577
     
    574582siproc (unsigned char c, struct rtems_termios_tty *tty)
    575583{
    576   int i;
    577 
    578   /*
    579   * Obtain output semaphore if character will be echoed
    580   */
    581   if (tty->termios.c_lflag & (ECHO|ECHOE|ECHOK|ECHONL|ECHOPRT|ECHOCTL|ECHOKE)) {
    582     rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
    583     i = iproc (c, tty);
    584     rtems_semaphore_release (tty->osem);
    585   }
    586   else {
    587     i = iproc (c, tty);
    588   }
    589   return i;
     584        int i;
     585
     586        /*
     587        * Obtain output semaphore if character will be echoed
     588        */
     589        if (tty->termios.c_lflag & (ECHO|ECHOE|ECHOK|ECHONL|ECHOPRT|ECHOCTL|ECHOKE)) {
     590                rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
     591                i = iproc (c, tty);
     592                rtems_semaphore_release (tty->osem);
     593        }
     594        else {
     595                i = iproc (c, tty);
     596        }
     597        return i;
    590598}
    591599
     
    596604fillBufferPoll (struct rtems_termios_tty *tty)
    597605{
    598   unsigned char c;
    599   int n;
    600 
    601   if (tty->termios.c_lflag & ICANON) {
    602     for (;;) {
    603       n = (*tty->read)(tty->minor, &c);
    604       if (n < 0) {
    605         return RTEMS_UNSATISFIED;
    606       }
    607       else if (n == 0) {
    608         rtems_task_wake_after (1);
    609       }
    610       else {
    611         if  (siproc (c, tty))
    612           break;
    613       }
    614     }
    615   }
    616   else {
    617     rtems_interval then, now;
    618     if (!tty->termios.c_cc[VMIN] && tty->termios.c_cc[VTIME])
    619       rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &then);
    620     for (;;) {
    621       n = (*tty->read)(tty->minor, &c);
    622       if (n < 0) {
    623         return RTEMS_UNSATISFIED;
    624       }
    625       else if (n == 0) {
    626         if (tty->termios.c_cc[VMIN]) {
    627           if (tty->termios.c_cc[VTIME] && tty->ccount) {
    628             rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
    629             if ((now - then) > tty->vtimeTicks) {
    630               break;
    631             }
    632           }
    633         }
    634         else {
    635           if (!tty->termios.c_cc[VTIME])
    636             break;
    637           rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
    638           if ((now - then) > tty->vtimeTicks) {
    639             break;
    640           }
    641         }
    642         rtems_task_wake_after (1);
    643       }
    644       else {
    645         siproc (c, tty);
    646         if (tty->ccount >= tty->termios.c_cc[VMIN])
    647           break;
    648         if (tty->termios.c_cc[VMIN] && tty->termios.c_cc[VTIME])
    649           rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &then);
    650       }
    651     }
    652   }
    653   return RTEMS_SUCCESSFUL;
     606        unsigned char c;
     607        int n;
     608
     609        if (tty->termios.c_lflag & ICANON) {
     610                for (;;) {
     611                        n = (*tty->read)(tty->minor, &c);
     612                        if (n < 0) {
     613                                return RTEMS_UNSATISFIED;
     614                        }
     615                        else if (n == 0) {
     616                                rtems_task_wake_after (1);
     617                        }
     618                        else {
     619                                if  (siproc (c, tty))
     620                                        break;
     621                        }
     622                }
     623        }
     624        else {
     625                rtems_interval then, now;
     626                if (!tty->termios.c_cc[VMIN] && tty->termios.c_cc[VTIME])
     627                        rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &then);
     628                for (;;) {
     629                        n = (*tty->read)(tty->minor, &c);
     630                        if (n < 0) {
     631                                return RTEMS_UNSATISFIED;
     632                        }
     633                        else if (n == 0) {
     634                                if (tty->termios.c_cc[VMIN]) {
     635                                        if (tty->termios.c_cc[VTIME] && tty->ccount) {
     636                                                rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
     637                                                if ((now - then) > tty->vtimeTicks) {
     638                                                        break;
     639                                                }
     640                                        }
     641                                }
     642                                else {
     643                                        if (!tty->termios.c_cc[VTIME])
     644                                                break;
     645                                        rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
     646                                        if ((now - then) > tty->vtimeTicks) {
     647                                                break;
     648                                        }
     649                                }
     650                                rtems_task_wake_after (1);
     651                        }
     652                        else {
     653                                siproc (c, tty);
     654                                if (tty->ccount >= tty->termios.c_cc[VMIN])
     655                                        break;
     656                                if (tty->termios.c_cc[VMIN] && tty->termios.c_cc[VTIME])
     657                                        rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &then);
     658                        }
     659                }
     660        }
     661        return RTEMS_SUCCESSFUL;
    654662}
    655663
     
    660668fillBufferQueue (struct rtems_termios_tty *tty)
    661669{
    662   rtems_interval timeout = tty->rawMessageFirstTimeout;
    663   rtems_status_code sc;
    664   rtems_unsigned8   c;
    665 
    666   for (;;) {
    667 
    668     /*
    669      * Read characters from raw queue
    670      */
    671     sc = rtems_semaphore_obtain (tty->rawInputSem,
    672               tty->rawMessageOptions,
    673               timeout);
    674     if (sc != RTEMS_SUCCESSFUL)
    675       break;
    676     Ring_buffer_Remove_character( &tty->rawInputBuffer, c );
    677 
    678    /*
    679     * Process characters read from raw queue
    680     */
    681     if (tty->termios.c_lflag & ICANON) {
    682       if  (siproc (c, tty))
    683         return RTEMS_SUCCESSFUL;
    684     }
    685     else {
    686       siproc (c, tty);
    687       if (tty->ccount >= tty->termios.c_cc[VMIN])
    688         return RTEMS_SUCCESSFUL;
    689     }
    690 
    691     timeout = tty->rawMessageTimeout;
    692   }
    693   return RTEMS_SUCCESSFUL;
     670        rtems_interval timeout = tty->rawBufSemaphoreFirstTimeout;
     671        rtems_status_code sc;
     672
     673        for (;;) {
     674                /*
     675                 * Process characters read from raw queue
     676                 */
     677                while (tty->rawBufHead != tty->rawBufTail) {
     678                        unsigned char c;
     679                        unsigned int newHead;
     680
     681                        newHead = (tty->rawBufHead + 1) % RAW_BUFFER_SIZE;
     682                        c = tty->rawBuf[newHead];
     683                        tty->rawBufHead = newHead;
     684                        if (tty->termios.c_lflag & ICANON) {
     685                                if  (siproc (c, tty))
     686                                        return RTEMS_SUCCESSFUL;
     687                        }
     688                        else {
     689                                siproc (c, tty);
     690                                if (tty->ccount >= tty->termios.c_cc[VMIN])
     691                                        return RTEMS_SUCCESSFUL;
     692                        }
     693                        timeout = tty->rawBufSemaphoreTimeout;
     694                }
     695
     696                /*
     697                 * Wait for characters
     698                 */
     699                sc = rtems_semaphore_obtain (tty->rawBufSemaphore,
     700                                                tty->rawBufSemaphoreOptions,
     701                                                timeout);
     702                if (sc != RTEMS_SUCCESSFUL)
     703                        break;
     704        }
     705        return RTEMS_SUCCESSFUL;
    694706}
    695707
     
    697709rtems_termios_read (void *arg)
    698710{
    699   rtems_libio_rw_args_t *args = arg;
    700   struct rtems_termios_tty *tty = args->iop->data1;
    701   unsigned32 count = args->count;
    702   unsigned8 *buffer = args->buffer;
    703   rtems_status_code sc;
    704 
    705   sc = rtems_semaphore_obtain (tty->isem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
    706   if (sc != RTEMS_SUCCESSFUL)
    707     return sc;
    708   if (tty->cindex == tty->ccount) {
    709     tty->cindex = tty->ccount = 0;
    710     tty->read_start_column = tty->column;
    711     if (tty->read)
    712       sc = fillBufferPoll (tty);
    713     else
    714       sc = fillBufferQueue (tty);
    715     if (sc != RTEMS_SUCCESSFUL)
    716       tty->cindex = tty->ccount = 0;
    717   }
    718   while (count && (tty->cindex < tty->ccount)) {
    719     *buffer++ = tty->cbuf[tty->cindex++];
    720     count--;
    721   }
    722   args->bytes_moved = args->count - count;
    723   rtems_semaphore_release (tty->isem);
    724   return sc;
     711        rtems_libio_rw_args_t *args = arg;
     712        struct rtems_termios_tty *tty = args->iop->data1;
     713        unsigned32 count = args->count;
     714        unsigned8 *buffer = args->buffer;
     715        rtems_status_code sc;
     716
     717        sc = rtems_semaphore_obtain (tty->isem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
     718        if (sc != RTEMS_SUCCESSFUL)
     719                return sc;
     720        if (tty->cindex == tty->ccount) {
     721                tty->cindex = tty->ccount = 0;
     722                tty->read_start_column = tty->column;
     723                if (tty->read)
     724                        sc = fillBufferPoll (tty);
     725                else
     726                        sc = fillBufferQueue (tty);
     727                if (sc != RTEMS_SUCCESSFUL)
     728                        tty->cindex = tty->ccount = 0;
     729        }
     730        while (count && (tty->cindex < tty->ccount)) {
     731                *buffer++ = tty->cbuf[tty->cindex++];
     732                count--;
     733        }
     734        args->bytes_moved = args->count - count;
     735        rtems_semaphore_release (tty->isem);
     736        return sc;
    725737}
    726738
     
    732744rtems_termios_enqueue_raw_characters (void *ttyp, char *buf, int len)
    733745{
    734   struct rtems_termios_tty *tty = ttyp;
    735 
    736   while (len) {
    737     if (Ring_buffer_Is_full(&tty->rawInputBuffer))
    738       break;
    739     Ring_buffer_Add_character(&tty->rawInputBuffer, *buf);
    740     if (rtems_semaphore_release(tty->rawInputSem) != RTEMS_SUCCESSFUL)
    741       break;
    742     len -= 1;
    743     buf += 1;
    744   }
    745 }
    746 
     746        struct rtems_termios_tty *tty = ttyp;
     747        unsigned int newTail;
     748
     749        while (len) {
     750                newTail = (tty->rawBufTail + 1) % RAW_BUFFER_SIZE;
     751                if (newTail == tty->rawBufHead) {
     752                        tty->rawBufDropped += len;
     753                        break;
     754                }
     755                tty->rawBuf[newTail] = *buf++;
     756                len--;
     757                tty->rawBufTail = newTail;
     758        }
     759        rtems_semaphore_release (tty->rawBufSemaphore);
     760}
     761
     762/*
     763 *  Reserve enough resources to at least open every physical device
     764 *  once.
     765 */
     766
     767void rtems_termios_reserve_resources(
     768  rtems_configuration_table *configuration,
     769  rtems_unsigned32           number_of_devices
     770)
     771{
     772  static int first_time = 1;
     773  rtems_api_configuration_table *rtems_config;
     774
     775  if (!configuration)
     776    rtems_fatal_error_occurred (0xFFF0F001);
     777
     778  rtems_config = configuration->RTEMS_api_configuration;
     779  if (!rtems_config)
     780    rtems_fatal_error_occurred (0xFFF0F002);
     781
     782  if (first_time)
     783    rtems_config->maximum_semaphores += 1;
     784
     785  first_time = 0;
     786  rtems_config->maximum_semaphores += (3 * number_of_devices);
     787}
  • c/src/lib/include/rtems/libio.h

    r3dbcece r118a812  
    148148rtems_status_code rtems_termios_ioctl (void *arg);
    149149void rtems_termios_enqueue_raw_characters (void *ttyp, char *buf, int len);
     150void rtems_termios_reserve_resources(
     151  rtems_configuration_table *configuration,
     152  rtems_unsigned32           number_of_devices
     153);
    150154
    151155#endif /* _RTEMS_LIBIO_H */
  • c/src/lib/libc/libio.h

    r3dbcece r118a812  
    148148rtems_status_code rtems_termios_ioctl (void *arg);
    149149void rtems_termios_enqueue_raw_characters (void *ttyp, char *buf, int len);
     150void rtems_termios_reserve_resources(
     151  rtems_configuration_table *configuration,
     152  rtems_unsigned32           number_of_devices
     153);
    150154
    151155#endif /* _RTEMS_LIBIO_H */
  • c/src/lib/libc/termios.c

    r3dbcece r118a812  
    2424#include <termios.h>
    2525#include <unistd.h>
    26 #include <ringbuf.h>
    2726
    2827/*
    2928 * The size of the cooked buffer
    3029 */
    31 #define CBUFSIZE  256
     30#define CBUFSIZE        256
     31
     32/*
     33 * The size of the raw input message queue
     34 */
     35#define RAW_BUFFER_SIZE 128
    3236
    3337/*
     
    3640 */
    3741struct rtems_termios_tty {
    38   /*
    39    * Linked-list of active TERMIOS devices
    40    */
    41   struct rtems_termios_tty  *forw;
    42   struct rtems_termios_tty  *back;
    43 
    44   /*
    45    * How many times has this device been opened
    46    */
    47   int   refcount;
    48 
    49   /*
    50    * This device
    51    */
    52   rtems_device_major_number major;
    53   rtems_device_major_number minor;
    54 
    55   /*
    56    * Mutual-exclusion semaphores
    57    */
    58   rtems_id  isem;
    59   rtems_id  osem;
    60 
    61   /*
    62    * The canonical (cooked) character buffer
    63    */
    64   char    cbuf[CBUFSIZE];
    65   int   ccount;
    66   int   cindex;
    67 
    68   /*
    69    * Keep track of cursor (printhead) position
    70    */
    71   int   column;
    72   int   read_start_column;
    73 
    74   /*
    75    * The ioctl settings
    76    */
    77   struct termios  termios;
    78   rtems_interval  vtimeTicks;
    79 
    80   /*
    81    * Raw character buffer
    82    */
    83   rtems_id      rawInputSem;
    84   Ring_buffer_t rawInputBuffer;
    85 
    86   rtems_unsigned32  rawMessageOptions;
    87   rtems_interval  rawMessageTimeout;
    88   rtems_interval  rawMessageFirstTimeout;
    89 
    90   /*
    91    * Callbacks to device-specific routines
    92    */
    93   int   (*lastClose)(int major, int minor, void *arg);
    94   int   (*read)(int minor, char *buf );
    95   int   (*write)(int minor, char *buf, int len);
     42        /*
     43         * Linked-list of active TERMIOS devices
     44         */
     45        struct rtems_termios_tty        *forw;
     46        struct rtems_termios_tty        *back;
     47
     48        /*
     49         * How many times has this device been opened
     50         */
     51        int             refcount;
     52
     53        /*
     54         * This device
     55         */
     56        rtems_device_major_number       major;
     57        rtems_device_major_number       minor;
     58
     59        /*
     60         * Mutual-exclusion semaphores
     61         */
     62        rtems_id        isem;
     63        rtems_id        osem;
     64
     65        /*
     66         * The canonical (cooked) character buffer
     67         */
     68        char            cbuf[CBUFSIZE];
     69        int             ccount;
     70        int             cindex;
     71
     72        /*
     73         * Keep track of cursor (printhead) position
     74         */
     75        int             column;
     76        int             read_start_column;
     77
     78        /*
     79         * The ioctl settings
     80         */
     81        struct termios  termios;
     82        rtems_interval  vtimeTicks;
     83
     84        /*
     85         * Raw character buffer
     86         */
     87        volatile char           rawBuf[RAW_BUFFER_SIZE];
     88        volatile unsigned int   rawBufHead;
     89        volatile unsigned int   rawBufTail;
     90        rtems_id                rawBufSemaphore;
     91        rtems_unsigned32        rawBufSemaphoreOptions;
     92        rtems_interval          rawBufSemaphoreTimeout;
     93        rtems_interval          rawBufSemaphoreFirstTimeout;
     94        unsigned int            rawBufDropped;  /* Statistics */
     95
     96        /*
     97         * Callbacks to device-specific routines
     98         */
     99        int             (*lastClose)(int major, int minor, void *arg);
     100        int             (*read)(int minor, char *buf);
     101        int             (*write)(int minor, char *buf, int len);
    96102};
    97103static struct rtems_termios_tty *ttyHead, *ttyTail;
     
    101107rtems_termios_initialize (void)
    102108{
    103   rtems_status_code sc;
    104 
    105   /*
    106   * Create the mutex semaphore for the tty list
    107   */
    108   if (!ttyMutex) {
    109     sc = rtems_semaphore_create (
    110       rtems_build_name ('T', 'R', 'm', 'i'),
    111       1,
    112       RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
    113       RTEMS_NO_PRIORITY,
    114       &ttyMutex);
    115     if (sc != RTEMS_SUCCESSFUL)
    116       rtems_fatal_error_occurred (sc);
    117   }
    118 }
    119  
     109        rtems_status_code sc;
     110
     111        /*
     112        * Create the mutex semaphore for the tty list
     113        */
     114        if (!ttyMutex) {
     115                sc = rtems_semaphore_create (
     116                        rtems_build_name ('T', 'R', 'm', 'i'),
     117                        1,
     118                        RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
     119                        RTEMS_NO_PRIORITY,
     120                        &ttyMutex);
     121                if (sc != RTEMS_SUCCESSFUL)
     122                        rtems_fatal_error_occurred (sc);
     123        }
     124}
     125       
    120126/*
    121127 * Open a termios device
     
    128134  int                      (*deviceFirstOpen)(int major, int minor, void *arg),
    129135  int                      (*deviceLastClose)(int major, int minor, void *arg),
    130   int                      (*deviceRead)(int minor, char *buf/*, int len*/),
     136  int                      (*deviceRead)(int minor, char *buf),
    131137  int                      (*deviceWrite)(int minor, char *buf, int len)
    132138  )
    133139{
    134   rtems_status_code sc;
    135   rtems_libio_open_close_args_t *args = arg;
    136   struct rtems_termios_tty *tty;
    137 
    138   /*
    139    * See if the device has already been opened
    140    */
    141   sc = rtems_semaphore_obtain (ttyMutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
    142   if (sc != RTEMS_SUCCESSFUL)
    143     return sc;
    144   for (tty = ttyHead ; tty != NULL ; tty = tty->forw) {
    145     if ((tty->major == major) && (tty->minor == minor))
    146       break;
    147   }
    148   if (tty == NULL) {
    149     static char c = 'a';
    150 
    151     /*
    152      * Create a new device
    153      */
    154     tty = malloc (sizeof (struct rtems_termios_tty));
    155     if (tty == NULL) {
    156       rtems_semaphore_release (ttyMutex);
    157       return RTEMS_NO_MEMORY;
    158     }
    159     tty->forw = ttyHead;
    160     ttyHead = tty;
    161     tty->back = NULL;
    162     if (ttyTail == NULL)
    163       ttyTail = tty;
    164 
    165     /*
    166      * Set up mutex semaphores
    167      */
    168     sc = rtems_semaphore_create (
    169       rtems_build_name ('T', 'R', 'i', c),
    170       1,
    171       RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
    172       RTEMS_NO_PRIORITY,
    173       &tty->isem);
    174     if (sc != RTEMS_SUCCESSFUL)
    175       rtems_fatal_error_occurred (sc);
    176     sc = rtems_semaphore_create (
    177       rtems_build_name ('T', 'R', 'o', c),
    178       1,
    179       RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
    180       RTEMS_NO_PRIORITY,
    181       &tty->osem);
    182     if (sc != RTEMS_SUCCESSFUL)
    183       rtems_fatal_error_occurred (sc);
    184 
    185     /*
    186      * Set callbacks
    187      */
    188     tty->write = deviceWrite;
    189     tty->lastClose = deviceLastClose;
    190     if ((tty->read = deviceRead) == NULL) {
    191       sc = rtems_semaphore_create (
    192         rtems_build_name ('T', 'R', 'r', c),
    193         0,
    194         RTEMS_COUNTING_SEMAPHORE | RTEMS_FIFO | RTEMS_LOCAL,
    195         RTEMS_NO_PRIORITY,
    196         &tty->rawInputSem);
    197       if (sc != RTEMS_SUCCESSFUL)
    198         rtems_fatal_error_occurred (sc);
    199     }
    200 
    201     /*
    202      * Initialize variables
    203      */
    204     tty->column = 0;
    205     tty->cindex = tty->ccount = 0;
    206 
    207     /*
    208      * Set default parameters
    209      */
    210     tty->termios.c_iflag = BRKINT | ICRNL | IXON | IMAXBEL;
    211     tty->termios.c_oflag = OPOST | ONLCR | XTABS;
    212     tty->termios.c_cflag = B9600 | CS8 | CREAD;
    213     tty->termios.c_lflag = ISIG | ICANON | IEXTEN | ECHO | ECHOK | ECHOE | ECHOCTL;
    214     tty->termios.c_cc[VINTR] = '\003';
    215     tty->termios.c_cc[VQUIT] = '\034';
    216     tty->termios.c_cc[VERASE] = '\177';
    217     tty->termios.c_cc[VKILL] = '\025';
    218     tty->termios.c_cc[VEOF] = '\004';
    219     tty->termios.c_cc[VEOL] = '\000';
    220     tty->termios.c_cc[VEOL2] = '\000';
    221     tty->termios.c_cc[VSTART] = '\021';
    222     tty->termios.c_cc[VSTOP] = '\023';
    223     tty->termios.c_cc[VSUSP] = '\032';
    224     tty->termios.c_cc[VREPRINT] = '\022';
    225     tty->termios.c_cc[VDISCARD] = '\017';
    226     tty->termios.c_cc[VWERASE] = '\027';
    227     tty->termios.c_cc[VLNEXT] = '\026';
    228 
    229     /*
    230      * Device-specific open
    231      */
    232     if (deviceFirstOpen)
    233       (*deviceFirstOpen) (major, minor, arg);
    234 
    235     /*
    236      * Bump name characer
    237      */
    238     if (c++ == 'z')
    239       c = 'a';
    240   }
    241   tty->refcount++;
    242   args->iop->data1 = tty;
    243   rtems_semaphore_release (ttyMutex);
    244   return RTEMS_SUCCESSFUL;
     140        rtems_status_code sc;
     141        rtems_libio_open_close_args_t *args = arg;
     142        struct rtems_termios_tty *tty;
     143
     144        /*
     145         * See if the device has already been opened
     146         */
     147        sc = rtems_semaphore_obtain (ttyMutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
     148        if (sc != RTEMS_SUCCESSFUL)
     149                return sc;
     150        for (tty = ttyHead ; tty != NULL ; tty = tty->forw) {
     151                if ((tty->major == major) && (tty->minor == minor))
     152                        break;
     153        }
     154        if (tty == NULL) {
     155                static char c = 'a';
     156
     157                /*
     158                 * Create a new device
     159                 */
     160                tty = malloc (sizeof (struct rtems_termios_tty));
     161                if (tty == NULL) {
     162                        rtems_semaphore_release (ttyMutex);
     163                        return RTEMS_NO_MEMORY;
     164                }
     165                tty->forw = ttyHead;
     166                ttyHead = tty;
     167                tty->back = NULL;
     168                if (ttyTail == NULL)
     169                        ttyTail = tty;
     170
     171                /*
     172                 * Set up mutex semaphores
     173                 */
     174                sc = rtems_semaphore_create (
     175                        rtems_build_name ('T', 'R', 'i', c),
     176                        1,
     177                        RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
     178                        RTEMS_NO_PRIORITY,
     179                        &tty->isem);
     180                if (sc != RTEMS_SUCCESSFUL)
     181                        rtems_fatal_error_occurred (sc);
     182                sc = rtems_semaphore_create (
     183                        rtems_build_name ('T', 'R', 'o', c),
     184                        1,
     185                        RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
     186                        RTEMS_NO_PRIORITY,
     187                        &tty->osem);
     188                if (sc != RTEMS_SUCCESSFUL)
     189                        rtems_fatal_error_occurred (sc);
     190
     191                /*
     192                 * Set callbacks
     193                 */
     194                tty->write = deviceWrite;
     195                tty->lastClose = deviceLastClose;
     196                if ((tty->read = deviceRead) == NULL) {
     197                        sc = rtems_semaphore_create (
     198                                rtems_build_name ('T', 'R', 'r', c),
     199                                0,
     200                                RTEMS_COUNTING_SEMAPHORE | RTEMS_PRIORITY,
     201                                RTEMS_NO_PRIORITY,
     202                                &tty->rawBufSemaphore);
     203                        if (sc != RTEMS_SUCCESSFUL)
     204                                rtems_fatal_error_occurred (sc);
     205                        tty->rawBufHead = 0;
     206                        tty->rawBufTail = 0;
     207                }
     208
     209                /*
     210                 * Initialize variables
     211                 */
     212                tty->column = 0;
     213                tty->cindex = tty->ccount = 0;
     214
     215                /*
     216                 * Set default parameters
     217                 */
     218                tty->termios.c_iflag = BRKINT | ICRNL | IXON | IMAXBEL;
     219                tty->termios.c_oflag = OPOST | ONLCR | XTABS;
     220                tty->termios.c_cflag = B9600 | CS8 | CREAD;
     221                tty->termios.c_lflag = ISIG | ICANON | IEXTEN | ECHO | ECHOK | ECHOE | ECHOCTL;
     222                tty->termios.c_cc[VINTR] = '\003';
     223                tty->termios.c_cc[VQUIT] = '\034';
     224                tty->termios.c_cc[VERASE] = '\177';
     225                tty->termios.c_cc[VKILL] = '\025';
     226                tty->termios.c_cc[VEOF] = '\004';
     227                tty->termios.c_cc[VEOL] = '\000';
     228                tty->termios.c_cc[VEOL2] = '\000';
     229                tty->termios.c_cc[VSTART] = '\021';
     230                tty->termios.c_cc[VSTOP] = '\023';
     231                tty->termios.c_cc[VSUSP] = '\032';
     232                tty->termios.c_cc[VREPRINT] = '\022';
     233                tty->termios.c_cc[VDISCARD] = '\017';
     234                tty->termios.c_cc[VWERASE] = '\027';
     235                tty->termios.c_cc[VLNEXT] = '\026';
     236
     237                /*
     238                 * Device-specific open
     239                 */
     240                if (deviceFirstOpen)
     241                        (*deviceFirstOpen) (major, minor, arg);
     242
     243                /*
     244                 * Bump name characer
     245                 */
     246                if (c++ == 'z')
     247                        c = 'a';
     248        }
     249        tty->refcount++;
     250        args->iop->data1 = tty;
     251        rtems_semaphore_release (ttyMutex);
     252        return RTEMS_SUCCESSFUL;
    245253}
    246254
     
    248256rtems_termios_close (void *arg)
    249257{
    250   rtems_libio_open_close_args_t *args = arg;
    251   struct rtems_termios_tty *tty = args->iop->data1;
    252   rtems_status_code sc;
    253 
    254   sc = rtems_semaphore_obtain (ttyMutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
    255   if (sc != RTEMS_SUCCESSFUL)
    256     rtems_fatal_error_occurred (sc);
    257   if (--tty->refcount == 0) {
    258     if (tty->lastClose)
    259       (*tty->lastClose) (tty->major, tty->minor, arg);
    260     if (tty->forw == NULL)
    261       ttyTail = tty->back;
    262     else
    263       tty->forw->back = tty->back;
    264     if (tty->back == NULL)
    265       ttyHead = tty->forw;
    266     else
    267       tty->back->forw = tty->forw;
    268     rtems_semaphore_delete (tty->isem);
    269     rtems_semaphore_delete (tty->osem);
    270     if (tty->read == NULL)
    271       rtems_semaphore_delete (tty->rawInputSem);
    272     free (tty);
    273   }
    274   rtems_semaphore_release (ttyMutex);
    275   return RTEMS_SUCCESSFUL;
     258        rtems_libio_open_close_args_t *args = arg;
     259        struct rtems_termios_tty *tty = args->iop->data1;
     260        rtems_status_code sc;
     261
     262        sc = rtems_semaphore_obtain (ttyMutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
     263        if (sc != RTEMS_SUCCESSFUL)
     264                rtems_fatal_error_occurred (sc);
     265        if (--tty->refcount == 0) {
     266                if (tty->lastClose)
     267                        (*tty->lastClose) (tty->major, tty->minor, arg);
     268                if (tty->forw == NULL)
     269                        ttyTail = tty->back;
     270                else
     271                        tty->forw->back = tty->back;
     272                if (tty->back == NULL)
     273                        ttyHead = tty->forw;
     274                else
     275                        tty->back->forw = tty->forw;
     276                rtems_semaphore_delete (tty->isem);
     277                rtems_semaphore_delete (tty->osem);
     278                if (tty->read == NULL)
     279                        rtems_semaphore_delete (tty->rawBufSemaphore);
     280                free (tty);
     281        }
     282        rtems_semaphore_release (ttyMutex);
     283        return RTEMS_SUCCESSFUL;
    276284}
    277285
     
    279287rtems_termios_ioctl (void *arg)
    280288{
    281   rtems_libio_ioctl_args_t *args = arg;
    282   struct rtems_termios_tty *tty = args->iop->data1;
    283   rtems_status_code sc;
    284 
    285   sc = rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
    286   if (sc != RTEMS_SUCCESSFUL)
    287     return sc;
    288   switch (args->command) {
    289   default:
    290     sc = RTEMS_INVALID_NUMBER;
    291     break;
    292 
    293   case RTEMS_IO_GET_ATTRIBUTES:
    294     *(struct termios *)args->buffer = tty->termios;
    295     break;
    296 
    297   case RTEMS_IO_SET_ATTRIBUTES:
    298     tty->termios = *(struct termios *)args->buffer;
    299     if (tty->termios.c_lflag & ICANON) {
    300       tty->rawMessageOptions = RTEMS_WAIT;
    301       tty->rawMessageTimeout = RTEMS_NO_TIMEOUT;
    302       tty->rawMessageFirstTimeout = RTEMS_NO_TIMEOUT;
    303     }
    304     else {
    305       rtems_interval ticksPerSecond;
    306       rtems_clock_get (RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticksPerSecond);
    307       tty->vtimeTicks = tty->termios.c_cc[VTIME] * ticksPerSecond / 10;
    308       if (tty->termios.c_cc[VTIME]) {
    309         tty->rawMessageOptions = RTEMS_WAIT;
    310         tty->rawMessageTimeout = tty->vtimeTicks;
    311         if (tty->termios.c_cc[VMIN])
    312           tty->rawMessageFirstTimeout = RTEMS_NO_TIMEOUT;
    313         else
    314           tty->rawMessageFirstTimeout = tty->vtimeTicks;
    315       }
    316       else {
    317         if (tty->termios.c_cc[VMIN]) {
    318           tty->rawMessageOptions = RTEMS_WAIT;
    319           tty->rawMessageTimeout = RTEMS_NO_TIMEOUT;
    320           tty->rawMessageFirstTimeout = RTEMS_NO_TIMEOUT;
    321         }
    322         else {
    323           tty->rawMessageOptions = RTEMS_NO_WAIT;
    324         }
    325       }
    326     }
    327     break;
    328   }
    329   rtems_semaphore_release (tty->osem);
    330   return sc;
     289        rtems_libio_ioctl_args_t *args = arg;
     290        struct rtems_termios_tty *tty = args->iop->data1;
     291        rtems_status_code sc;
     292
     293        sc = rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
     294        if (sc != RTEMS_SUCCESSFUL)
     295                return sc;
     296        switch (args->command) {
     297        default:
     298                sc = RTEMS_INVALID_NUMBER;
     299                break;
     300
     301        case RTEMS_IO_GET_ATTRIBUTES:
     302                *(struct termios *)args->buffer = tty->termios;
     303                break;
     304
     305        case RTEMS_IO_SET_ATTRIBUTES:
     306                tty->termios = *(struct termios *)args->buffer;
     307                if (tty->termios.c_lflag & ICANON) {
     308                        tty->rawBufSemaphoreOptions = RTEMS_WAIT;
     309                        tty->rawBufSemaphoreTimeout = RTEMS_NO_TIMEOUT;
     310                        tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
     311                }
     312                else {
     313                        rtems_interval ticksPerSecond;
     314                        rtems_clock_get (RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticksPerSecond);
     315                        tty->vtimeTicks = tty->termios.c_cc[VTIME] * ticksPerSecond / 10;
     316                        if (tty->termios.c_cc[VTIME]) {
     317                                tty->rawBufSemaphoreOptions = RTEMS_WAIT;
     318                                tty->rawBufSemap`oreTimeout = tty->vtimeTicks;
     319                                if (tty->termios.c_cc[VMIN])
     320                                        tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
     321                                else
     322                                        tty->rawBufSemaphoreFirstTimeout = tty->vtimeTicks;
     323                        }
     324                        else {
     325                                if (tty->termios.c_cc[VMIN]) {
     326                                        tty->rawBufSemaphoreOptions = RTEMS_WAIT;
     327                                        tty->rawBufSemaphoreTimeout = RTEMS_NO_TIMEOUT;
     328                                        tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
     329                                }
     330                                else {
     331                                        tty->rawBufSemaphoreOptions = RTEMS_NO_WAIT;
     332                                }
     333                        }
     334                }
     335                break;
     336        }
     337        rtems_semaphore_release (tty->osem);
     338        return sc;
    331339}
    332340
     
    337345oproc (unsigned char c, struct rtems_termios_tty *tty)
    338346{
    339   int i;
    340 
    341   if (tty->termios.c_oflag & OPOST) {
    342     switch (c) {
    343     case '\n':
    344       if (tty->termios.c_oflag & ONLRET)
    345         tty->column = 0;
    346       if (tty->termios.c_oflag & ONLCR) {
    347         (*tty->write)(tty->minor, "\r", 1);
    348         tty->column = 0;
    349       }
    350       break;
    351 
    352     case '\r':
    353       if ((tty->termios.c_oflag & ONOCR) && (tty->column == 0))
    354         return;
    355       if (tty->termios.c_oflag & OCRNL) {
    356         c = '\n';
    357         if (tty->termios.c_oflag & ONLRET)
    358           tty->column = 0;
    359         break;
    360       }
    361       tty->column = 0;
    362       break;
    363 
    364     case '\t':
    365       i = 8 - (tty->column & 7);
    366       if ((tty->termios.c_oflag & TABDLY) == XTABS) {
    367         tty->column += i;
    368         (*tty->write)(tty->minor,  "        ",  i);
    369         return;
    370       }
    371       tty->column += i;
    372       break;
    373 
    374     case '\b':
    375       if (tty->column > 0)
    376         tty->column--;
    377       break;
    378 
    379     default:
    380       if (tty->termios.c_oflag & OLCUC)
    381         c = toupper(c);
    382       if (!iscntrl(c))
    383         tty->column++;
    384       break;
    385     }
    386   }
    387   (*tty->write)(tty->minor, &c, 1);
     347        int     i;
     348
     349        if (tty->termios.c_oflag & OPOST) {
     350                switch (c) {
     351                case '\n':
     352                        if (tty->termios.c_oflag & ONLRET)
     353                                tty->column = 0;
     354                        if (tty->termios.c_oflag & ONLCR) {
     355                                (*tty->write)(tty->minor, "\r", 1);
     356                                tty->column = 0;
     357                        }
     358                        break;
     359
     360                case '\r':
     361                        if ((tty->termios.c_oflag & ONOCR) && (tty->column == 0))
     362                                return;
     363                        if (tty->termios.c_oflag & OCRNL) {
     364                                c = '\n';
     365                                if (tty->termios.c_oflag & ONLRET)
     366                                        tty->column = 0;
     367                                break;
     368                        }
     369                        tty->column = 0;
     370                        break;
     371
     372                case '\t':
     373                        i = 8 - (tty->column & 7);
     374                        if ((tty->termios.c_oflag & TABDLY) == XTABS) {
     375                                tty->column += i;
     376                                (*tty->write)(tty->minor,  "        ",  i);
     377                                return;
     378                        }
     379                        tty->column += i;
     380                        break;
     381
     382                case '\b':
     383                        if (tty->column > 0)
     384                                tty->column--;
     385                        break;
     386
     387                default:
     388                        if (tty->termios.c_oflag & OLCUC)
     389                                c = toupper(c);
     390                        if (!iscntrl(c))
     391                                tty->column++;
     392                        break;
     393                }
     394        }
     395        (*tty->write)(tty->minor, &c, 1);
    388396}
    389397
     
    391399rtems_termios_write (void *arg)
    392400{
    393   rtems_libio_rw_args_t *args = arg;
    394   struct rtems_termios_tty *tty = args->iop->data1;
    395   rtems_status_code sc;
    396 
    397   sc = rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
    398   if (sc != RTEMS_SUCCESSFUL)
    399     return sc;
    400   if (tty->termios.c_oflag & OPOST) {
    401     unsigned32 count = args->count;
    402     unsigned8 *buffer = args->buffer;
    403     while (count--)
    404       oproc (*buffer++, tty);
    405     args->bytes_moved = args->count;
    406   }
    407   else {
    408     if ((*tty->write)(tty->minor, args->buffer, args->count) < 0)
    409       sc = RTEMS_UNSATISFIED;
    410     else
    411       args->bytes_moved = args->count;
    412   }
    413   rtems_semaphore_release (tty->osem);
    414   return sc;
     401        rtems_libio_rw_args_t *args = arg;
     402        struct rtems_termios_tty *tty = args->iop->data1;
     403        rtems_status_code sc;
     404
     405        sc = rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
     406        if (sc != RTEMS_SUCCESSFUL)
     407                return sc;
     408        if (tty->termios.c_oflag & OPOST) {
     409                unsigned32 count = args->count;
     410                unsigned8 *buffer = args->buffer;
     411                while (count--)
     412                        oproc (*buffer++, tty);
     413                args->bytes_moved = args->count;
     414        }
     415        else {
     416                if ((*tty->write)(tty->minor, args->buffer, args->count) < 0)
     417                        sc = RTEMS_UNSATISFIED;
     418                else
     419                        args->bytes_moved = args->count;
     420        }
     421        rtems_semaphore_release (tty->osem);
     422        return sc;
    415423}
    416424
     
    421429echo (unsigned char c, struct rtems_termios_tty *tty)
    422430{
    423   if ((tty->termios.c_lflag & ECHOCTL) && iscntrl(c) && (c != '\t') && (c != '\n')) {
    424     char echobuf[2];
    425 
    426     echobuf[0] = '^';
    427     echobuf[1] = c ^ 0x40;
    428     (*tty->write)(tty->minor, echobuf, 2);
    429     tty->column += 2;
    430   }
    431   else {
    432     oproc (c, tty);
    433   }
     431        if ((tty->termios.c_lflag & ECHOCTL) && iscntrl(c) && (c != '\t') && (c != '\n')) {
     432                char echobuf[2];
     433
     434                echobuf[0] = '^';
     435                echobuf[1] = c ^ 0x40;
     436                (*tty->write)(tty->minor, echobuf, 2);
     437                tty->column += 2;
     438        }
     439        else {
     440                oproc (c, tty);
     441        }
    434442}
    435443
     
    442450erase (struct rtems_termios_tty *tty, int lineFlag)
    443451{
    444   if (tty->ccount == 0)
    445     return;
    446   if (lineFlag) {
    447     if (!(tty->termios.c_lflag & ECHO)) {
    448       tty->ccount = 0;
    449       return;
    450     }
    451     if (!(tty->termios.c_lflag & ECHOE)) {
    452       tty->ccount = 0;
    453       echo (tty->termios.c_cc[VKILL], tty);
    454       if (tty->termios.c_lflag & ECHOK)
    455         echo ('\n', tty);
    456       return;
    457     }
    458   }
    459   while (tty->ccount) {
    460     unsigned char c = tty->cbuf[--tty->ccount];
    461 
    462     if (tty->termios.c_lflag & ECHO) {
    463       if (!lineFlag && !(tty->termios.c_lflag & ECHOE)) {
    464         echo (tty->termios.c_cc[VERASE], tty);
    465       }
    466       else if (c == '\t') {
    467         int col = tty->read_start_column;
    468         int i = 0;
    469 
    470         /*
    471         * Find the character before the tab
    472         */
    473         while (i != tty->ccount) {
    474           c = tty->cbuf[i++];
    475           if (c == '\t') {
    476             col = (col | 7) + 1;
    477           }
    478           else if (iscntrl (c)) {
    479             if (tty->termios.c_lflag & ECHOCTL)
    480               col += 2;
    481           }
    482           else {
    483             col++;
    484           }
    485         }
    486 
    487         /*
    488         * Back up over the tab
    489         */
    490         while (tty->column > col) {
    491           (*tty->write)(tty->minor, "\b", 1);
    492           tty->column--;
    493         }
    494       }
    495       else {
    496         if (iscntrl (c) && (tty->termios.c_lflag & ECHOCTL)) {
    497           (*tty->write)(tty->minor, "\b \b", 3);
    498           if (tty->column)
    499             tty->column--;
    500         }
    501         if (!iscntrl (c) || (tty->termios.c_lflag & ECHOCTL)) {
    502           (*tty->write)(tty->minor, "\b \b", 3);
    503           if (tty->column)
    504             tty->column--;
    505         }
    506       }
    507     }
    508     if (!lineFlag)
    509       break;
    510   }
     452        if (tty->ccount == 0)
     453                return;
     454        if (lineFlag) {
     455                if (!(tty->termios.c_lflag & ECHO)) {
     456                        tty->ccount = 0;
     457                        return;
     458                }
     459                if (!(tty->termios.c_lflag & ECHOE)) {
     460                        tty->ccount = 0;
     461                        echo (tty->termios.c_cc[VKILL], tty);
     462                        if (tty->termios.c_lflag & ECHOK)
     463                                echo ('\n', tty);
     464                        return;
     465                }
     466        }
     467        while (tty->ccount) {
     468                unsigned char c = tty->cbuf[--tty->ccount];
     469
     470                if (tty->termios.c_lflag & ECHO) {
     471                        if (!lineFlag && !(tty->termios.c_lflag & ECHOE)) {
     472                                echo (tty->termios.c_cc[VERASE], tty);
     473                        }
     474                        else if (c == '\t') {
     475                                int col = tty->read_start_column;
     476                                int i = 0;
     477
     478                                /*
     479                                * Find the character before the tab
     480                                */
     481                                while (i != tty->ccount) {
     482                                        c = tty->cbuf[i++];
     483                                        if (c == '\t') {
     484                                                col = (col | 7) + 1;
     485                                        }
     486                                        else if (iscntrl (c)) {
     487                                                if (tty->termios.c_lflag & ECHOCTL)
     488                                                        col += 2;
     489                                        }
     490                                        else {
     491                                                col++;
     492                                        }
     493                                }
     494
     495                                /*
     496                                * Back up over the tab
     497                                */
     498                                while (tty->column > col) {
     499                                        (*tty->write)(tty->minor, "\b", 1);
     500                                        tty->column--;
     501                                }
     502                        }
     503                        else {
     504                                if (iscntrl (c) && (tty->termios.c_lflag & ECHOCTL)) {
     505                                        (*tty->write)(tty->minor, "\b \b", 3);
     506                                        if (tty->column)
     507                                                tty->column--;
     508                                }
     509                                if (!iscntrl (c) || (tty->termios.c_lflag & ECHOCTL)) {
     510                                        (*tty->write)(tty->minor, "\b \b", 3);
     511                                        if (tty->column)
     512                                                tty->column--;
     513                                }
     514                        }
     515                }
     516                if (!lineFlag)
     517                        break;
     518        }
    511519}
    512520
     
    517525iproc (unsigned char c, struct rtems_termios_tty *tty)
    518526{
    519   if (tty->termios.c_iflag & ISTRIP)
    520     c &= 0x7f;
    521   if (tty->termios.c_iflag & IUCLC)
    522     c = tolower (c);
    523   if (c == '\r') {
    524     if (tty->termios.c_iflag & IGNCR)
    525       return 0;
    526     if (tty->termios.c_iflag & ICRNL)
    527       c = '\n';
    528   }
    529   else if ((c == '\n') && (tty->termios.c_iflag & INLCR)) {
    530     c = '\r';
    531   }
    532   if ((c != '\0') && (tty->termios.c_lflag & ICANON)) {
    533     if (c == tty->termios.c_cc[VERASE]) {
    534       erase (tty, 0);
    535       return 0;
    536     }
    537     else if (c == tty->termios.c_cc[VKILL]) {
    538       erase (tty, 1);
    539       return 0;
    540     }
    541     else if (c == tty->termios.c_cc[VEOF]) {
    542       return 1;
    543     }
    544     else if (c == '\n') {
    545       if (tty->termios.c_lflag & (ECHO | ECHONL))
    546         echo (c, tty);
    547       tty->cbuf[tty->ccount++] = c;
    548       return 1;
    549     }
    550     else if ((c == tty->termios.c_cc[VEOL])
    551           || (c == tty->termios.c_cc[VEOL2])) {
    552       if (tty->termios.c_lflag & ECHO)
    553         echo (c, tty);
    554       tty->cbuf[tty->ccount++] = c;
    555       return 1;
    556     }
    557   }
    558 
    559   /*
    560   * FIXME: Should do IMAXBEL handling somehow
    561   */
    562   if (tty->ccount < (CBUFSIZE-1)) {
    563     if (tty->termios.c_lflag & ECHO)
    564       echo (c, tty);
    565     tty->cbuf[tty->ccount++] = c;
    566   }
    567   return 0;
     527        if (tty->termios.c_iflag & ISTRIP)
     528                c &= 0x7f;
     529        if (tty->termios.c_iflag & IUCLC)
     530                c = tolower (c);
     531        if (c == '\r') {
     532                if (tty->termios.c_iflag & IGNCR)
     533                        return 0;
     534                if (tty->termios.c_iflag & ICRNL)
     535                        c = '\n';
     536        }
     537        else if ((c == '\n') && (tty->termios.c_iflag & INLCR)) {
     538                c = '\r';
     539        }
     540        if ((c != '\0') && (tty->termios.c_lflag & ICANON)) {
     541                if (c == tty->termios.c_cc[VERASE]) {
     542                        erase (tty, 0);
     543                        return 0;
     544                }
     545                else if (c == tty->termios.c_cc[VKILL]) {
     546                        erase (tty, 1);
     547                        return 0;
     548                }
     549                else if (c == tty->termios.c_cc[VEOF]) {
     550                        return 1;
     551                }
     552                else if (c == '\n') {
     553                        if (tty->termios.c_lflag & (ECHO | ECHONL))
     554                                echo (c, tty);
     555                        tty->cbuf[tty->ccount++] = c;
     556                        return 1;
     557                }
     558                else if ((c == tty->termios.c_cc[VEOL])
     559                      || (c == tty->termios.c_cc[VEOL2])) {
     560                        if (tty->termios.c_lflag & ECHO)
     561                                echo (c, tty);
     562                        tty->cbuf[tty->ccount++] = c;
     563                        return 1;
     564                }
     565        }
     566
     567        /*
     568        * FIXME: Should do IMAXBEL handling somehow
     569        */
     570        if (tty->ccount < (CBUFSIZE-1)) {
     571                if (tty->termios.c_lflag & ECHO)
     572                        echo (c, tty);
     573                tty->cbuf[tty->ccount++] = c;
     574        }
     575        return 0;
    568576}
    569577
     
    574582siproc (unsigned char c, struct rtems_termios_tty *tty)
    575583{
    576   int i;
    577 
    578   /*
    579   * Obtain output semaphore if character will be echoed
    580   */
    581   if (tty->termios.c_lflag & (ECHO|ECHOE|ECHOK|ECHONL|ECHOPRT|ECHOCTL|ECHOKE)) {
    582     rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
    583     i = iproc (c, tty);
    584     rtems_semaphore_release (tty->osem);
    585   }
    586   else {
    587     i = iproc (c, tty);
    588   }
    589   return i;
     584        int i;
     585
     586        /*
     587        * Obtain output semaphore if character will be echoed
     588        */
     589        if (tty->termios.c_lflag & (ECHO|ECHOE|ECHOK|ECHONL|ECHOPRT|ECHOCTL|ECHOKE)) {
     590                rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
     591                i = iproc (c, tty);
     592                rtems_semaphore_release (tty->osem);
     593        }
     594        else {
     595                i = iproc (c, tty);
     596        }
     597        return i;
    590598}
    591599
     
    596604fillBufferPoll (struct rtems_termios_tty *tty)
    597605{
    598   unsigned char c;
    599   int n;
    600 
    601   if (tty->termios.c_lflag & ICANON) {
    602     for (;;) {
    603       n = (*tty->read)(tty->minor, &c);
    604       if (n < 0) {
    605         return RTEMS_UNSATISFIED;
    606       }
    607       else if (n == 0) {
    608         rtems_task_wake_after (1);
    609       }
    610       else {
    611         if  (siproc (c, tty))
    612           break;
    613       }
    614     }
    615   }
    616   else {
    617     rtems_interval then, now;
    618     if (!tty->termios.c_cc[VMIN] && tty->termios.c_cc[VTIME])
    619       rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &then);
    620     for (;;) {
    621       n = (*tty->read)(tty->minor, &c);
    622       if (n < 0) {
    623         return RTEMS_UNSATISFIED;
    624       }
    625       else if (n == 0) {
    626         if (tty->termios.c_cc[VMIN]) {
    627           if (tty->termios.c_cc[VTIME] && tty->ccount) {
    628             rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
    629             if ((now - then) > tty->vtimeTicks) {
    630               break;
    631             }
    632           }
    633         }
    634         else {
    635           if (!tty->termios.c_cc[VTIME])
    636             break;
    637           rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
    638           if ((now - then) > tty->vtimeTicks) {
    639             break;
    640           }
    641         }
    642         rtems_task_wake_after (1);
    643       }
    644       else {
    645         siproc (c, tty);
    646         if (tty->ccount >= tty->termios.c_cc[VMIN])
    647           break;
    648         if (tty->termios.c_cc[VMIN] && tty->termios.c_cc[VTIME])
    649           rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &then);
    650       }
    651     }
    652   }
    653   return RTEMS_SUCCESSFUL;
     606        unsigned char c;
     607        int n;
     608
     609        if (tty->termios.c_lflag & ICANON) {
     610                for (;;) {
     611                        n = (*tty->read)(tty->minor, &c);
     612                        if (n < 0) {
     613                                return RTEMS_UNSATISFIED;
     614                        }
     615                        else if (n == 0) {
     616                                rtems_task_wake_after (1);
     617                        }
     618                        else {
     619                                if  (siproc (c, tty))
     620                                        break;
     621                        }
     622                }
     623        }
     624        else {
     625                rtems_interval then, now;
     626                if (!tty->termios.c_cc[VMIN] && tty->termios.c_cc[VTIME])
     627                        rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &then);
     628                for (;;) {
     629                        n = (*tty->read)(tty->minor, &c);
     630                        if (n < 0) {
     631                                return RTEMS_UNSATISFIED;
     632                        }
     633                        else if (n == 0) {
     634                                if (tty->termios.c_cc[VMIN]) {
     635                                        if (tty->termios.c_cc[VTIME] && tty->ccount) {
     636                                                rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
     637                                                if ((now - then) > tty->vtimeTicks) {
     638                                                        break;
     639                                                }
     640                                        }
     641                                }
     642                                else {
     643                                        if (!tty->termios.c_cc[VTIME])
     644                                                break;
     645                                        rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
     646                                        if ((now - then) > tty->vtimeTicks) {
     647                                                break;
     648                                        }
     649                                }
     650                                rtems_task_wake_after (1);
     651                        }
     652                        else {
     653                                siproc (c, tty);
     654                                if (tty->ccount >= tty->termios.c_cc[VMIN])
     655                                        break;
     656                                if (tty->termios.c_cc[VMIN] && tty->termios.c_cc[VTIME])
     657                                        rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &then);
     658                        }
     659                }
     660        }
     661        return RTEMS_SUCCESSFUL;
    654662}
    655663
     
    660668fillBufferQueue (struct rtems_termios_tty *tty)
    661669{
    662   rtems_interval timeout = tty->rawMessageFirstTimeout;
    663   rtems_status_code sc;
    664   rtems_unsigned8   c;
    665 
    666   for (;;) {
    667 
    668     /*
    669      * Read characters from raw queue
    670      */
    671     sc = rtems_semaphore_obtain (tty->rawInputSem,
    672               tty->rawMessageOptions,
    673               timeout);
    674     if (sc != RTEMS_SUCCESSFUL)
    675       break;
    676     Ring_buffer_Remove_character( &tty->rawInputBuffer, c );
    677 
    678    /*
    679     * Process characters read from raw queue
    680     */
    681     if (tty->termios.c_lflag & ICANON) {
    682       if  (siproc (c, tty))
    683         return RTEMS_SUCCESSFUL;
    684     }
    685     else {
    686       siproc (c, tty);
    687       if (tty->ccount >= tty->termios.c_cc[VMIN])
    688         return RTEMS_SUCCESSFUL;
    689     }
    690 
    691     timeout = tty->rawMessageTimeout;
    692   }
    693   return RTEMS_SUCCESSFUL;
     670        rtems_interval timeout = tty->rawBufSemaphoreFirstTimeout;
     671        rtems_status_code sc;
     672
     673        for (;;) {
     674                /*
     675                 * Process characters read from raw queue
     676                 */
     677                while (tty->rawBufHead != tty->rawBufTail) {
     678                        unsigned char c;
     679                        unsigned int newHead;
     680
     681                        newHead = (tty->rawBufHead + 1) % RAW_BUFFER_SIZE;
     682                        c = tty->rawBuf[newHead];
     683                        tty->rawBufHead = newHead;
     684                        if (tty->termios.c_lflag & ICANON) {
     685                                if  (siproc (c, tty))
     686                                        return RTEMS_SUCCESSFUL;
     687                        }
     688                        else {
     689                                siproc (c, tty);
     690                                if (tty->ccount >= tty->termios.c_cc[VMIN])
     691                                        return RTEMS_SUCCESSFUL;
     692                        }
     693                        timeout = tty->rawBufSemaphoreTimeout;
     694                }
     695
     696                /*
     697                 * Wait for characters
     698                 */
     699                sc = rtems_semaphore_obtain (tty->rawBufSemaphore,
     700                                                tty->rawBufSemaphoreOptions,
     701                                                timeout);
     702                if (sc != RTEMS_SUCCESSFUL)
     703                        break;
     704        }
     705        return RTEMS_SUCCESSFUL;
    694706}
    695707
     
    697709rtems_termios_read (void *arg)
    698710{
    699   rtems_libio_rw_args_t *args = arg;
    700   struct rtems_termios_tty *tty = args->iop->data1;
    701   unsigned32 count = args->count;
    702   unsigned8 *buffer = args->buffer;
    703   rtems_status_code sc;
    704 
    705   sc = rtems_semaphore_obtain (tty->isem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
    706   if (sc != RTEMS_SUCCESSFUL)
    707     return sc;
    708   if (tty->cindex == tty->ccount) {
    709     tty->cindex = tty->ccount = 0;
    710     tty->read_start_column = tty->column;
    711     if (tty->read)
    712       sc = fillBufferPoll (tty);
    713     else
    714       sc = fillBufferQueue (tty);
    715     if (sc != RTEMS_SUCCESSFUL)
    716       tty->cindex = tty->ccount = 0;
    717   }
    718   while (count && (tty->cindex < tty->ccount)) {
    719     *buffer++ = tty->cbuf[tty->cindex++];
    720     count--;
    721   }
    722   args->bytes_moved = args->count - count;
    723   rtems_semaphore_release (tty->isem);
    724   return sc;
     711        rtems_libio_rw_args_t *args = arg;
     712        struct rtems_termios_tty *tty = args->iop->data1;
     713        unsigned32 count = args->count;
     714        unsigned8 *buffer = args->buffer;
     715        rtems_status_code sc;
     716
     717        sc = rtems_semaphore_obtain (tty->isem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
     718        if (sc != RTEMS_SUCCESSFUL)
     719                return sc;
     720        if (tty->cindex == tty->ccount) {
     721                tty->cindex = tty->ccount = 0;
     722                tty->read_start_column = tty->column;
     723                if (tty->read)
     724                        sc = fillBufferPoll (tty);
     725                else
     726                        sc = fillBufferQueue (tty);
     727                if (sc != RTEMS_SUCCESSFUL)
     728                        tty->cindex = tty->ccount = 0;
     729        }
     730        while (count && (tty->cindex < tty->ccount)) {
     731                *buffer++ = tty->cbuf[tty->cindex++];
     732                count--;
     733        }
     734        args->bytes_moved = args->count - count;
     735        rtems_semaphore_release (tty->isem);
     736        return sc;
    725737}
    726738
     
    732744rtems_termios_enqueue_raw_characters (void *ttyp, char *buf, int len)
    733745{
    734   struct rtems_termios_tty *tty = ttyp;
    735 
    736   while (len) {
    737     if (Ring_buffer_Is_full(&tty->rawInputBuffer))
    738       break;
    739     Ring_buffer_Add_character(&tty->rawInputBuffer, *buf);
    740     if (rtems_semaphore_release(tty->rawInputSem) != RTEMS_SUCCESSFUL)
    741       break;
    742     len -= 1;
    743     buf += 1;
    744   }
    745 }
    746 
     746        struct rtems_termios_tty *tty = ttyp;
     747        unsigned int newTail;
     748
     749        while (len) {
     750                newTail = (tty->rawBufTail + 1) % RAW_BUFFER_SIZE;
     751                if (newTail == tty->rawBufHead) {
     752                        tty->rawBufDropped += len;
     753                        break;
     754                }
     755                tty->rawBuf[newTail] = *buf++;
     756                len--;
     757                tty->rawBufTail = newTail;
     758        }
     759        rtems_semaphore_release (tty->rawBufSemaphore);
     760}
     761
     762/*
     763 *  Reserve enough resources to at least open every physical device
     764 *  once.
     765 */
     766
     767void rtems_termios_reserve_resources(
     768  rtems_configuration_table *configuration,
     769  rtems_unsigned32           number_of_devices
     770)
     771{
     772  static int first_time = 1;
     773  rtems_api_configuration_table *rtems_config;
     774
     775  if (!configuration)
     776    rtems_fatal_error_occurred (0xFFF0F001);
     777
     778  rtems_config = configuration->RTEMS_api_configuration;
     779  if (!rtems_config)
     780    rtems_fatal_error_occurred (0xFFF0F002);
     781
     782  if (first_time)
     783    rtems_config->maximum_semaphores += 1;
     784
     785  first_time = 0;
     786  rtems_config->maximum_semaphores += (3 * number_of_devices);
     787}
  • cpukit/libcsupport/include/rtems/libio.h

    r3dbcece r118a812  
    148148rtems_status_code rtems_termios_ioctl (void *arg);
    149149void rtems_termios_enqueue_raw_characters (void *ttyp, char *buf, int len);
     150void rtems_termios_reserve_resources(
     151  rtems_configuration_table *configuration,
     152  rtems_unsigned32           number_of_devices
     153);
    150154
    151155#endif /* _RTEMS_LIBIO_H */
  • cpukit/libcsupport/src/termios.c

    r3dbcece r118a812  
    2424#include <termios.h>
    2525#include <unistd.h>
    26 #include <ringbuf.h>
    2726
    2827/*
    2928 * The size of the cooked buffer
    3029 */
    31 #define CBUFSIZE  256
     30#define CBUFSIZE        256
     31
     32/*
     33 * The size of the raw input message queue
     34 */
     35#define RAW_BUFFER_SIZE 128
    3236
    3337/*
     
    3640 */
    3741struct rtems_termios_tty {
    38   /*
    39    * Linked-list of active TERMIOS devices
    40    */
    41   struct rtems_termios_tty  *forw;
    42   struct rtems_termios_tty  *back;
    43 
    44   /*
    45    * How many times has this device been opened
    46    */
    47   int   refcount;
    48 
    49   /*
    50    * This device
    51    */
    52   rtems_device_major_number major;
    53   rtems_device_major_number minor;
    54 
    55   /*
    56    * Mutual-exclusion semaphores
    57    */
    58   rtems_id  isem;
    59   rtems_id  osem;
    60 
    61   /*
    62    * The canonical (cooked) character buffer
    63    */
    64   char    cbuf[CBUFSIZE];
    65   int   ccount;
    66   int   cindex;
    67 
    68   /*
    69    * Keep track of cursor (printhead) position
    70    */
    71   int   column;
    72   int   read_start_column;
    73 
    74   /*
    75    * The ioctl settings
    76    */
    77   struct termios  termios;
    78   rtems_interval  vtimeTicks;
    79 
    80   /*
    81    * Raw character buffer
    82    */
    83   rtems_id      rawInputSem;
    84   Ring_buffer_t rawInputBuffer;
    85 
    86   rtems_unsigned32  rawMessageOptions;
    87   rtems_interval  rawMessageTimeout;
    88   rtems_interval  rawMessageFirstTimeout;
    89 
    90   /*
    91    * Callbacks to device-specific routines
    92    */
    93   int   (*lastClose)(int major, int minor, void *arg);
    94   int   (*read)(int minor, char *buf );
    95   int   (*write)(int minor, char *buf, int len);
     42        /*
     43         * Linked-list of active TERMIOS devices
     44         */
     45        struct rtems_termios_tty        *forw;
     46        struct rtems_termios_tty        *back;
     47
     48        /*
     49         * How many times has this device been opened
     50         */
     51        int             refcount;
     52
     53        /*
     54         * This device
     55         */
     56        rtems_device_major_number       major;
     57        rtems_device_major_number       minor;
     58
     59        /*
     60         * Mutual-exclusion semaphores
     61         */
     62        rtems_id        isem;
     63        rtems_id        osem;
     64
     65        /*
     66         * The canonical (cooked) character buffer
     67         */
     68        char            cbuf[CBUFSIZE];
     69        int             ccount;
     70        int             cindex;
     71
     72        /*
     73         * Keep track of cursor (printhead) position
     74         */
     75        int             column;
     76        int             read_start_column;
     77
     78        /*
     79         * The ioctl settings
     80         */
     81        struct termios  termios;
     82        rtems_interval  vtimeTicks;
     83
     84        /*
     85         * Raw character buffer
     86         */
     87        volatile char           rawBuf[RAW_BUFFER_SIZE];
     88        volatile unsigned int   rawBufHead;
     89        volatile unsigned int   rawBufTail;
     90        rtems_id                rawBufSemaphore;
     91        rtems_unsigned32        rawBufSemaphoreOptions;
     92        rtems_interval          rawBufSemaphoreTimeout;
     93        rtems_interval          rawBufSemaphoreFirstTimeout;
     94        unsigned int            rawBufDropped;  /* Statistics */
     95
     96        /*
     97         * Callbacks to device-specific routines
     98         */
     99        int             (*lastClose)(int major, int minor, void *arg);
     100        int             (*read)(int minor, char *buf);
     101        int             (*write)(int minor, char *buf, int len);
    96102};
    97103static struct rtems_termios_tty *ttyHead, *ttyTail;
     
    101107rtems_termios_initialize (void)
    102108{
    103   rtems_status_code sc;
    104 
    105   /*
    106   * Create the mutex semaphore for the tty list
    107   */
    108   if (!ttyMutex) {
    109     sc = rtems_semaphore_create (
    110       rtems_build_name ('T', 'R', 'm', 'i'),
    111       1,
    112       RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
    113       RTEMS_NO_PRIORITY,
    114       &ttyMutex);
    115     if (sc != RTEMS_SUCCESSFUL)
    116       rtems_fatal_error_occurred (sc);
    117   }
    118 }
    119  
     109        rtems_status_code sc;
     110
     111        /*
     112        * Create the mutex semaphore for the tty list
     113        */
     114        if (!ttyMutex) {
     115                sc = rtems_semaphore_create (
     116                        rtems_build_name ('T', 'R', 'm', 'i'),
     117                        1,
     118                        RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
     119                        RTEMS_NO_PRIORITY,
     120                        &ttyMutex);
     121                if (sc != RTEMS_SUCCESSFUL)
     122                        rtems_fatal_error_occurred (sc);
     123        }
     124}
     125       
    120126/*
    121127 * Open a termios device
     
    128134  int                      (*deviceFirstOpen)(int major, int minor, void *arg),
    129135  int                      (*deviceLastClose)(int major, int minor, void *arg),
    130   int                      (*deviceRead)(int minor, char *buf/*, int len*/),
     136  int                      (*deviceRead)(int minor, char *buf),
    131137  int                      (*deviceWrite)(int minor, char *buf, int len)
    132138  )
    133139{
    134   rtems_status_code sc;
    135   rtems_libio_open_close_args_t *args = arg;
    136   struct rtems_termios_tty *tty;
    137 
    138   /*
    139    * See if the device has already been opened
    140    */
    141   sc = rtems_semaphore_obtain (ttyMutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
    142   if (sc != RTEMS_SUCCESSFUL)
    143     return sc;
    144   for (tty = ttyHead ; tty != NULL ; tty = tty->forw) {
    145     if ((tty->major == major) && (tty->minor == minor))
    146       break;
    147   }
    148   if (tty == NULL) {
    149     static char c = 'a';
    150 
    151     /*
    152      * Create a new device
    153      */
    154     tty = malloc (sizeof (struct rtems_termios_tty));
    155     if (tty == NULL) {
    156       rtems_semaphore_release (ttyMutex);
    157       return RTEMS_NO_MEMORY;
    158     }
    159     tty->forw = ttyHead;
    160     ttyHead = tty;
    161     tty->back = NULL;
    162     if (ttyTail == NULL)
    163       ttyTail = tty;
    164 
    165     /*
    166      * Set up mutex semaphores
    167      */
    168     sc = rtems_semaphore_create (
    169       rtems_build_name ('T', 'R', 'i', c),
    170       1,
    171       RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
    172       RTEMS_NO_PRIORITY,
    173       &tty->isem);
    174     if (sc != RTEMS_SUCCESSFUL)
    175       rtems_fatal_error_occurred (sc);
    176     sc = rtems_semaphore_create (
    177       rtems_build_name ('T', 'R', 'o', c),
    178       1,
    179       RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
    180       RTEMS_NO_PRIORITY,
    181       &tty->osem);
    182     if (sc != RTEMS_SUCCESSFUL)
    183       rtems_fatal_error_occurred (sc);
    184 
    185     /*
    186      * Set callbacks
    187      */
    188     tty->write = deviceWrite;
    189     tty->lastClose = deviceLastClose;
    190     if ((tty->read = deviceRead) == NULL) {
    191       sc = rtems_semaphore_create (
    192         rtems_build_name ('T', 'R', 'r', c),
    193         0,
    194         RTEMS_COUNTING_SEMAPHORE | RTEMS_FIFO | RTEMS_LOCAL,
    195         RTEMS_NO_PRIORITY,
    196         &tty->rawInputSem);
    197       if (sc != RTEMS_SUCCESSFUL)
    198         rtems_fatal_error_occurred (sc);
    199     }
    200 
    201     /*
    202      * Initialize variables
    203      */
    204     tty->column = 0;
    205     tty->cindex = tty->ccount = 0;
    206 
    207     /*
    208      * Set default parameters
    209      */
    210     tty->termios.c_iflag = BRKINT | ICRNL | IXON | IMAXBEL;
    211     tty->termios.c_oflag = OPOST | ONLCR | XTABS;
    212     tty->termios.c_cflag = B9600 | CS8 | CREAD;
    213     tty->termios.c_lflag = ISIG | ICANON | IEXTEN | ECHO | ECHOK | ECHOE | ECHOCTL;
    214     tty->termios.c_cc[VINTR] = '\003';
    215     tty->termios.c_cc[VQUIT] = '\034';
    216     tty->termios.c_cc[VERASE] = '\177';
    217     tty->termios.c_cc[VKILL] = '\025';
    218     tty->termios.c_cc[VEOF] = '\004';
    219     tty->termios.c_cc[VEOL] = '\000';
    220     tty->termios.c_cc[VEOL2] = '\000';
    221     tty->termios.c_cc[VSTART] = '\021';
    222     tty->termios.c_cc[VSTOP] = '\023';
    223     tty->termios.c_cc[VSUSP] = '\032';
    224     tty->termios.c_cc[VREPRINT] = '\022';
    225     tty->termios.c_cc[VDISCARD] = '\017';
    226     tty->termios.c_cc[VWERASE] = '\027';
    227     tty->termios.c_cc[VLNEXT] = '\026';
    228 
    229     /*
    230      * Device-specific open
    231      */
    232     if (deviceFirstOpen)
    233       (*deviceFirstOpen) (major, minor, arg);
    234 
    235     /*
    236      * Bump name characer
    237      */
    238     if (c++ == 'z')
    239       c = 'a';
    240   }
    241   tty->refcount++;
    242   args->iop->data1 = tty;
    243   rtems_semaphore_release (ttyMutex);
    244   return RTEMS_SUCCESSFUL;
     140        rtems_status_code sc;
     141        rtems_libio_open_close_args_t *args = arg;
     142        struct rtems_termios_tty *tty;
     143
     144        /*
     145         * See if the device has already been opened
     146         */
     147        sc = rtems_semaphore_obtain (ttyMutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
     148        if (sc != RTEMS_SUCCESSFUL)
     149                return sc;
     150        for (tty = ttyHead ; tty != NULL ; tty = tty->forw) {
     151                if ((tty->major == major) && (tty->minor == minor))
     152                        break;
     153        }
     154        if (tty == NULL) {
     155                static char c = 'a';
     156
     157                /*
     158                 * Create a new device
     159                 */
     160                tty = malloc (sizeof (struct rtems_termios_tty));
     161                if (tty == NULL) {
     162                        rtems_semaphore_release (ttyMutex);
     163                        return RTEMS_NO_MEMORY;
     164                }
     165                tty->forw = ttyHead;
     166                ttyHead = tty;
     167                tty->back = NULL;
     168                if (ttyTail == NULL)
     169                        ttyTail = tty;
     170
     171                /*
     172                 * Set up mutex semaphores
     173                 */
     174                sc = rtems_semaphore_create (
     175                        rtems_build_name ('T', 'R', 'i', c),
     176                        1,
     177                        RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
     178                        RTEMS_NO_PRIORITY,
     179                        &tty->isem);
     180                if (sc != RTEMS_SUCCESSFUL)
     181                        rtems_fatal_error_occurred (sc);
     182                sc = rtems_semaphore_create (
     183                        rtems_build_name ('T', 'R', 'o', c),
     184                        1,
     185                        RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
     186                        RTEMS_NO_PRIORITY,
     187                        &tty->osem);
     188                if (sc != RTEMS_SUCCESSFUL)
     189                        rtems_fatal_error_occurred (sc);
     190
     191                /*
     192                 * Set callbacks
     193                 */
     194                tty->write = deviceWrite;
     195                tty->lastClose = deviceLastClose;
     196                if ((tty->read = deviceRead) == NULL) {
     197                        sc = rtems_semaphore_create (
     198                                rtems_build_name ('T', 'R', 'r', c),
     199                                0,
     200                                RTEMS_COUNTING_SEMAPHORE | RTEMS_PRIORITY,
     201                                RTEMS_NO_PRIORITY,
     202                                &tty->rawBufSemaphore);
     203                        if (sc != RTEMS_SUCCESSFUL)
     204                                rtems_fatal_error_occurred (sc);
     205                        tty->rawBufHead = 0;
     206                        tty->rawBufTail = 0;
     207                }
     208
     209                /*
     210                 * Initialize variables
     211                 */
     212                tty->column = 0;
     213                tty->cindex = tty->ccount = 0;
     214
     215                /*
     216                 * Set default parameters
     217                 */
     218                tty->termios.c_iflag = BRKINT | ICRNL | IXON | IMAXBEL;
     219                tty->termios.c_oflag = OPOST | ONLCR | XTABS;
     220                tty->termios.c_cflag = B9600 | CS8 | CREAD;
     221                tty->termios.c_lflag = ISIG | ICANON | IEXTEN | ECHO | ECHOK | ECHOE | ECHOCTL;
     222                tty->termios.c_cc[VINTR] = '\003';
     223                tty->termios.c_cc[VQUIT] = '\034';
     224                tty->termios.c_cc[VERASE] = '\177';
     225                tty->termios.c_cc[VKILL] = '\025';
     226                tty->termios.c_cc[VEOF] = '\004';
     227                tty->termios.c_cc[VEOL] = '\000';
     228                tty->termios.c_cc[VEOL2] = '\000';
     229                tty->termios.c_cc[VSTART] = '\021';
     230                tty->termios.c_cc[VSTOP] = '\023';
     231                tty->termios.c_cc[VSUSP] = '\032';
     232                tty->termios.c_cc[VREPRINT] = '\022';
     233                tty->termios.c_cc[VDISCARD] = '\017';
     234                tty->termios.c_cc[VWERASE] = '\027';
     235                tty->termios.c_cc[VLNEXT] = '\026';
     236
     237                /*
     238                 * Device-specific open
     239                 */
     240                if (deviceFirstOpen)
     241                        (*deviceFirstOpen) (major, minor, arg);
     242
     243                /*
     244                 * Bump name characer
     245                 */
     246                if (c++ == 'z')
     247                        c = 'a';
     248        }
     249        tty->refcount++;
     250        args->iop->data1 = tty;
     251        rtems_semaphore_release (ttyMutex);
     252        return RTEMS_SUCCESSFUL;
    245253}
    246254
     
    248256rtems_termios_close (void *arg)
    249257{
    250   rtems_libio_open_close_args_t *args = arg;
    251   struct rtems_termios_tty *tty = args->iop->data1;
    252   rtems_status_code sc;
    253 
    254   sc = rtems_semaphore_obtain (ttyMutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
    255   if (sc != RTEMS_SUCCESSFUL)
    256     rtems_fatal_error_occurred (sc);
    257   if (--tty->refcount == 0) {
    258     if (tty->lastClose)
    259       (*tty->lastClose) (tty->major, tty->minor, arg);
    260     if (tty->forw == NULL)
    261       ttyTail = tty->back;
    262     else
    263       tty->forw->back = tty->back;
    264     if (tty->back == NULL)
    265       ttyHead = tty->forw;
    266     else
    267       tty->back->forw = tty->forw;
    268     rtems_semaphore_delete (tty->isem);
    269     rtems_semaphore_delete (tty->osem);
    270     if (tty->read == NULL)
    271       rtems_semaphore_delete (tty->rawInputSem);
    272     free (tty);
    273   }
    274   rtems_semaphore_release (ttyMutex);
    275   return RTEMS_SUCCESSFUL;
     258        rtems_libio_open_close_args_t *args = arg;
     259        struct rtems_termios_tty *tty = args->iop->data1;
     260        rtems_status_code sc;
     261
     262        sc = rtems_semaphore_obtain (ttyMutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
     263        if (sc != RTEMS_SUCCESSFUL)
     264                rtems_fatal_error_occurred (sc);
     265        if (--tty->refcount == 0) {
     266                if (tty->lastClose)
     267                        (*tty->lastClose) (tty->major, tty->minor, arg);
     268                if (tty->forw == NULL)
     269                        ttyTail = tty->back;
     270                else
     271                        tty->forw->back = tty->back;
     272                if (tty->back == NULL)
     273                        ttyHead = tty->forw;
     274                else
     275                        tty->back->forw = tty->forw;
     276                rtems_semaphore_delete (tty->isem);
     277                rtems_semaphore_delete (tty->osem);
     278                if (tty->read == NULL)
     279                        rtems_semaphore_delete (tty->rawBufSemaphore);
     280                free (tty);
     281        }
     282        rtems_semaphore_release (ttyMutex);
     283        return RTEMS_SUCCESSFUL;
    276284}
    277285
     
    279287rtems_termios_ioctl (void *arg)
    280288{
    281   rtems_libio_ioctl_args_t *args = arg;
    282   struct rtems_termios_tty *tty = args->iop->data1;
    283   rtems_status_code sc;
    284 
    285   sc = rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
    286   if (sc != RTEMS_SUCCESSFUL)
    287     return sc;
    288   switch (args->command) {
    289   default:
    290     sc = RTEMS_INVALID_NUMBER;
    291     break;
    292 
    293   case RTEMS_IO_GET_ATTRIBUTES:
    294     *(struct termios *)args->buffer = tty->termios;
    295     break;
    296 
    297   case RTEMS_IO_SET_ATTRIBUTES:
    298     tty->termios = *(struct termios *)args->buffer;
    299     if (tty->termios.c_lflag & ICANON) {
    300       tty->rawMessageOptions = RTEMS_WAIT;
    301       tty->rawMessageTimeout = RTEMS_NO_TIMEOUT;
    302       tty->rawMessageFirstTimeout = RTEMS_NO_TIMEOUT;
    303     }
    304     else {
    305       rtems_interval ticksPerSecond;
    306       rtems_clock_get (RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticksPerSecond);
    307       tty->vtimeTicks = tty->termios.c_cc[VTIME] * ticksPerSecond / 10;
    308       if (tty->termios.c_cc[VTIME]) {
    309         tty->rawMessageOptions = RTEMS_WAIT;
    310         tty->rawMessageTimeout = tty->vtimeTicks;
    311         if (tty->termios.c_cc[VMIN])
    312           tty->rawMessageFirstTimeout = RTEMS_NO_TIMEOUT;
    313         else
    314           tty->rawMessageFirstTimeout = tty->vtimeTicks;
    315       }
    316       else {
    317         if (tty->termios.c_cc[VMIN]) {
    318           tty->rawMessageOptions = RTEMS_WAIT;
    319           tty->rawMessageTimeout = RTEMS_NO_TIMEOUT;
    320           tty->rawMessageFirstTimeout = RTEMS_NO_TIMEOUT;
    321         }
    322         else {
    323           tty->rawMessageOptions = RTEMS_NO_WAIT;
    324         }
    325       }
    326     }
    327     break;
    328   }
    329   rtems_semaphore_release (tty->osem);
    330   return sc;
     289        rtems_libio_ioctl_args_t *args = arg;
     290        struct rtems_termios_tty *tty = args->iop->data1;
     291        rtems_status_code sc;
     292
     293        sc = rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
     294        if (sc != RTEMS_SUCCESSFUL)
     295                return sc;
     296        switch (args->command) {
     297        default:
     298                sc = RTEMS_INVALID_NUMBER;
     299                break;
     300
     301        case RTEMS_IO_GET_ATTRIBUTES:
     302                *(struct termios *)args->buffer = tty->termios;
     303                break;
     304
     305        case RTEMS_IO_SET_ATTRIBUTES:
     306                tty->termios = *(struct termios *)args->buffer;
     307                if (tty->termios.c_lflag & ICANON) {
     308                        tty->rawBufSemaphoreOptions = RTEMS_WAIT;
     309                        tty->rawBufSemaphoreTimeout = RTEMS_NO_TIMEOUT;
     310                        tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
     311                }
     312                else {
     313                        rtems_interval ticksPerSecond;
     314                        rtems_clock_get (RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticksPerSecond);
     315                        tty->vtimeTicks = tty->termios.c_cc[VTIME] * ticksPerSecond / 10;
     316                        if (tty->termios.c_cc[VTIME]) {
     317                                tty->rawBufSemaphoreOptions = RTEMS_WAIT;
     318                                tty->rawBufSemap`oreTimeout = tty->vtimeTicks;
     319                                if (tty->termios.c_cc[VMIN])
     320                                        tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
     321                                else
     322                                        tty->rawBufSemaphoreFirstTimeout = tty->vtimeTicks;
     323                        }
     324                        else {
     325                                if (tty->termios.c_cc[VMIN]) {
     326                                        tty->rawBufSemaphoreOptions = RTEMS_WAIT;
     327                                        tty->rawBufSemaphoreTimeout = RTEMS_NO_TIMEOUT;
     328                                        tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
     329                                }
     330                                else {
     331                                        tty->rawBufSemaphoreOptions = RTEMS_NO_WAIT;
     332                                }
     333                        }
     334                }
     335                break;
     336        }
     337        rtems_semaphore_release (tty->osem);
     338        return sc;
    331339}
    332340
     
    337345oproc (unsigned char c, struct rtems_termios_tty *tty)
    338346{
    339   int i;
    340 
    341   if (tty->termios.c_oflag & OPOST) {
    342     switch (c) {
    343     case '\n':
    344       if (tty->termios.c_oflag & ONLRET)
    345         tty->column = 0;
    346       if (tty->termios.c_oflag & ONLCR) {
    347         (*tty->write)(tty->minor, "\r", 1);
    348         tty->column = 0;
    349       }
    350       break;
    351 
    352     case '\r':
    353       if ((tty->termios.c_oflag & ONOCR) && (tty->column == 0))
    354         return;
    355       if (tty->termios.c_oflag & OCRNL) {
    356         c = '\n';
    357         if (tty->termios.c_oflag & ONLRET)
    358           tty->column = 0;
    359         break;
    360       }
    361       tty->column = 0;
    362       break;
    363 
    364     case '\t':
    365       i = 8 - (tty->column & 7);
    366       if ((tty->termios.c_oflag & TABDLY) == XTABS) {
    367         tty->column += i;
    368         (*tty->write)(tty->minor,  "        ",  i);
    369         return;
    370       }
    371       tty->column += i;
    372       break;
    373 
    374     case '\b':
    375       if (tty->column > 0)
    376         tty->column--;
    377       break;
    378 
    379     default:
    380       if (tty->termios.c_oflag & OLCUC)
    381         c = toupper(c);
    382       if (!iscntrl(c))
    383         tty->column++;
    384       break;
    385     }
    386   }
    387   (*tty->write)(tty->minor, &c, 1);
     347        int     i;
     348
     349        if (tty->termios.c_oflag & OPOST) {
     350                switch (c) {
     351                case '\n':
     352                        if (tty->termios.c_oflag & ONLRET)
     353                                tty->column = 0;
     354                        if (tty->termios.c_oflag & ONLCR) {
     355                                (*tty->write)(tty->minor, "\r", 1);
     356                                tty->column = 0;
     357                        }
     358                        break;
     359
     360                case '\r':
     361                        if ((tty->termios.c_oflag & ONOCR) && (tty->column == 0))
     362                                return;
     363                        if (tty->termios.c_oflag & OCRNL) {
     364                                c = '\n';
     365                                if (tty->termios.c_oflag & ONLRET)
     366                                        tty->column = 0;
     367                                break;
     368                        }
     369                        tty->column = 0;
     370                        break;
     371
     372                case '\t':
     373                        i = 8 - (tty->column & 7);
     374                        if ((tty->termios.c_oflag & TABDLY) == XTABS) {
     375                                tty->column += i;
     376                                (*tty->write)(tty->minor,  "        ",  i);
     377                                return;
     378                        }
     379                        tty->column += i;
     380                        break;
     381
     382                case '\b':
     383                        if (tty->column > 0)
     384                                tty->column--;
     385                        break;
     386
     387                default:
     388                        if (tty->termios.c_oflag & OLCUC)
     389                                c = toupper(c);
     390                        if (!iscntrl(c))
     391                                tty->column++;
     392                        break;
     393                }
     394        }
     395        (*tty->write)(tty->minor, &c, 1);
    388396}
    389397
     
    391399rtems_termios_write (void *arg)
    392400{
    393   rtems_libio_rw_args_t *args = arg;
    394   struct rtems_termios_tty *tty = args->iop->data1;
    395   rtems_status_code sc;
    396 
    397   sc = rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
    398   if (sc != RTEMS_SUCCESSFUL)
    399     return sc;
    400   if (tty->termios.c_oflag & OPOST) {
    401     unsigned32 count = args->count;
    402     unsigned8 *buffer = args->buffer;
    403     while (count--)
    404       oproc (*buffer++, tty);
    405     args->bytes_moved = args->count;
    406   }
    407   else {
    408     if ((*tty->write)(tty->minor, args->buffer, args->count) < 0)
    409       sc = RTEMS_UNSATISFIED;
    410     else
    411       args->bytes_moved = args->count;
    412   }
    413   rtems_semaphore_release (tty->osem);
    414   return sc;
     401        rtems_libio_rw_args_t *args = arg;
     402        struct rtems_termios_tty *tty = args->iop->data1;
     403        rtems_status_code sc;
     404
     405        sc = rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
     406        if (sc != RTEMS_SUCCESSFUL)
     407                return sc;
     408        if (tty->termios.c_oflag & OPOST) {
     409                unsigned32 count = args->count;
     410                unsigned8 *buffer = args->buffer;
     411                while (count--)
     412                        oproc (*buffer++, tty);
     413                args->bytes_moved = args->count;
     414        }
     415        else {
     416                if ((*tty->write)(tty->minor, args->buffer, args->count) < 0)
     417                        sc = RTEMS_UNSATISFIED;
     418                else
     419                        args->bytes_moved = args->count;
     420        }
     421        rtems_semaphore_release (tty->osem);
     422        return sc;
    415423}
    416424
     
    421429echo (unsigned char c, struct rtems_termios_tty *tty)
    422430{
    423   if ((tty->termios.c_lflag & ECHOCTL) && iscntrl(c) && (c != '\t') && (c != '\n')) {
    424     char echobuf[2];
    425 
    426     echobuf[0] = '^';
    427     echobuf[1] = c ^ 0x40;
    428     (*tty->write)(tty->minor, echobuf, 2);
    429     tty->column += 2;
    430   }
    431   else {
    432     oproc (c, tty);
    433   }
     431        if ((tty->termios.c_lflag & ECHOCTL) && iscntrl(c) && (c != '\t') && (c != '\n')) {
     432                char echobuf[2];
     433
     434                echobuf[0] = '^';
     435                echobuf[1] = c ^ 0x40;
     436                (*tty->write)(tty->minor, echobuf, 2);
     437                tty->column += 2;
     438        }
     439        else {
     440                oproc (c, tty);
     441        }
    434442}
    435443
     
    442450erase (struct rtems_termios_tty *tty, int lineFlag)
    443451{
    444   if (tty->ccount == 0)
    445     return;
    446   if (lineFlag) {
    447     if (!(tty->termios.c_lflag & ECHO)) {
    448       tty->ccount = 0;
    449       return;
    450     }
    451     if (!(tty->termios.c_lflag & ECHOE)) {
    452       tty->ccount = 0;
    453       echo (tty->termios.c_cc[VKILL], tty);
    454       if (tty->termios.c_lflag & ECHOK)
    455         echo ('\n', tty);
    456       return;
    457     }
    458   }
    459   while (tty->ccount) {
    460     unsigned char c = tty->cbuf[--tty->ccount];
    461 
    462     if (tty->termios.c_lflag & ECHO) {
    463       if (!lineFlag && !(tty->termios.c_lflag & ECHOE)) {
    464         echo (tty->termios.c_cc[VERASE], tty);
    465       }
    466       else if (c == '\t') {
    467         int col = tty->read_start_column;
    468         int i = 0;
    469 
    470         /*
    471         * Find the character before the tab
    472         */
    473         while (i != tty->ccount) {
    474           c = tty->cbuf[i++];
    475           if (c == '\t') {
    476             col = (col | 7) + 1;
    477           }
    478           else if (iscntrl (c)) {
    479             if (tty->termios.c_lflag & ECHOCTL)
    480               col += 2;
    481           }
    482           else {
    483             col++;
    484           }
    485         }
    486 
    487         /*
    488         * Back up over the tab
    489         */
    490         while (tty->column > col) {
    491           (*tty->write)(tty->minor, "\b", 1);
    492           tty->column--;
    493         }
    494       }
    495       else {
    496         if (iscntrl (c) && (tty->termios.c_lflag & ECHOCTL)) {
    497           (*tty->write)(tty->minor, "\b \b", 3);
    498           if (tty->column)
    499             tty->column--;
    500         }
    501         if (!iscntrl (c) || (tty->termios.c_lflag & ECHOCTL)) {
    502           (*tty->write)(tty->minor, "\b \b", 3);
    503           if (tty->column)
    504             tty->column--;
    505         }
    506       }
    507     }
    508     if (!lineFlag)
    509       break;
    510   }
     452        if (tty->ccount == 0)
     453                return;
     454        if (lineFlag) {
     455                if (!(tty->termios.c_lflag & ECHO)) {
     456                        tty->ccount = 0;
     457                        return;
     458                }
     459                if (!(tty->termios.c_lflag & ECHOE)) {
     460                        tty->ccount = 0;
     461                        echo (tty->termios.c_cc[VKILL], tty);
     462                        if (tty->termios.c_lflag & ECHOK)
     463                                echo ('\n', tty);
     464                        return;
     465                }
     466        }
     467        while (tty->ccount) {
     468                unsigned char c = tty->cbuf[--tty->ccount];
     469
     470                if (tty->termios.c_lflag & ECHO) {
     471                        if (!lineFlag && !(tty->termios.c_lflag & ECHOE)) {
     472                                echo (tty->termios.c_cc[VERASE], tty);
     473                        }
     474                        else if (c == '\t') {
     475                                int col = tty->read_start_column;
     476                                int i = 0;
     477
     478                                /*
     479                                * Find the character before the tab
     480                                */
     481                                while (i != tty->ccount) {
     482                                        c = tty->cbuf[i++];
     483                                        if (c == '\t') {
     484                                                col = (col | 7) + 1;
     485                                        }
     486                                        else if (iscntrl (c)) {
     487                                                if (tty->termios.c_lflag & ECHOCTL)
     488                                                        col += 2;
     489                                        }
     490                                        else {
     491                                                col++;
     492                                        }
     493                                }
     494
     495                                /*
     496                                * Back up over the tab
     497                                */
     498                                while (tty->column > col) {
     499                                        (*tty->write)(tty->minor, "\b", 1);
     500                                        tty->column--;
     501                                }
     502                        }
     503                        else {
     504                                if (iscntrl (c) && (tty->termios.c_lflag & ECHOCTL)) {
     505                                        (*tty->write)(tty->minor, "\b \b", 3);
     506                                        if (tty->column)
     507                                                tty->column--;
     508                                }
     509                                if (!iscntrl (c) || (tty->termios.c_lflag & ECHOCTL)) {
     510                                        (*tty->write)(tty->minor, "\b \b", 3);
     511                                        if (tty->column)
     512                                                tty->column--;
     513                                }
     514                        }
     515                }
     516                if (!lineFlag)
     517                        break;
     518        }
    511519}
    512520
     
    517525iproc (unsigned char c, struct rtems_termios_tty *tty)
    518526{
    519   if (tty->termios.c_iflag & ISTRIP)
    520     c &= 0x7f;
    521   if (tty->termios.c_iflag & IUCLC)
    522     c = tolower (c);
    523   if (c == '\r') {
    524     if (tty->termios.c_iflag & IGNCR)
    525       return 0;
    526     if (tty->termios.c_iflag & ICRNL)
    527       c = '\n';
    528   }
    529   else if ((c == '\n') && (tty->termios.c_iflag & INLCR)) {
    530     c = '\r';
    531   }
    532   if ((c != '\0') && (tty->termios.c_lflag & ICANON)) {
    533     if (c == tty->termios.c_cc[VERASE]) {
    534       erase (tty, 0);
    535       return 0;
    536     }
    537     else if (c == tty->termios.c_cc[VKILL]) {
    538       erase (tty, 1);
    539       return 0;
    540     }
    541     else if (c == tty->termios.c_cc[VEOF]) {
    542       return 1;
    543     }
    544     else if (c == '\n') {
    545       if (tty->termios.c_lflag & (ECHO | ECHONL))
    546         echo (c, tty);
    547       tty->cbuf[tty->ccount++] = c;
    548       return 1;
    549     }
    550     else if ((c == tty->termios.c_cc[VEOL])
    551           || (c == tty->termios.c_cc[VEOL2])) {
    552       if (tty->termios.c_lflag & ECHO)
    553         echo (c, tty);
    554       tty->cbuf[tty->ccount++] = c;
    555       return 1;
    556     }
    557   }
    558 
    559   /*
    560   * FIXME: Should do IMAXBEL handling somehow
    561   */
    562   if (tty->ccount < (CBUFSIZE-1)) {
    563     if (tty->termios.c_lflag & ECHO)
    564       echo (c, tty);
    565     tty->cbuf[tty->ccount++] = c;
    566   }
    567   return 0;
     527        if (tty->termios.c_iflag & ISTRIP)
     528                c &= 0x7f;
     529        if (tty->termios.c_iflag & IUCLC)
     530                c = tolower (c);
     531        if (c == '\r') {
     532                if (tty->termios.c_iflag & IGNCR)
     533                        return 0;
     534                if (tty->termios.c_iflag & ICRNL)
     535                        c = '\n';
     536        }
     537        else if ((c == '\n') && (tty->termios.c_iflag & INLCR)) {
     538                c = '\r';
     539        }
     540        if ((c != '\0') && (tty->termios.c_lflag & ICANON)) {
     541                if (c == tty->termios.c_cc[VERASE]) {
     542                        erase (tty, 0);
     543                        return 0;
     544                }
     545                else if (c == tty->termios.c_cc[VKILL]) {
     546                        erase (tty, 1);
     547                        return 0;
     548                }
     549                else if (c == tty->termios.c_cc[VEOF]) {
     550                        return 1;
     551                }
     552                else if (c == '\n') {
     553                        if (tty->termios.c_lflag & (ECHO | ECHONL))
     554                                echo (c, tty);
     555                        tty->cbuf[tty->ccount++] = c;
     556                        return 1;
     557                }
     558                else if ((c == tty->termios.c_cc[VEOL])
     559                      || (c == tty->termios.c_cc[VEOL2])) {
     560                        if (tty->termios.c_lflag & ECHO)
     561                                echo (c, tty);
     562                        tty->cbuf[tty->ccount++] = c;
     563                        return 1;
     564                }
     565        }
     566
     567        /*
     568        * FIXME: Should do IMAXBEL handling somehow
     569        */
     570        if (tty->ccount < (CBUFSIZE-1)) {
     571                if (tty->termios.c_lflag & ECHO)
     572                        echo (c, tty);
     573                tty->cbuf[tty->ccount++] = c;
     574        }
     575        return 0;
    568576}
    569577
     
    574582siproc (unsigned char c, struct rtems_termios_tty *tty)
    575583{
    576   int i;
    577 
    578   /*
    579   * Obtain output semaphore if character will be echoed
    580   */
    581   if (tty->termios.c_lflag & (ECHO|ECHOE|ECHOK|ECHONL|ECHOPRT|ECHOCTL|ECHOKE)) {
    582     rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
    583     i = iproc (c, tty);
    584     rtems_semaphore_release (tty->osem);
    585   }
    586   else {
    587     i = iproc (c, tty);
    588   }
    589   return i;
     584        int i;
     585
     586        /*
     587        * Obtain output semaphore if character will be echoed
     588        */
     589        if (tty->termios.c_lflag & (ECHO|ECHOE|ECHOK|ECHONL|ECHOPRT|ECHOCTL|ECHOKE)) {
     590                rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
     591                i = iproc (c, tty);
     592                rtems_semaphore_release (tty->osem);
     593        }
     594        else {
     595                i = iproc (c, tty);
     596        }
     597        return i;
    590598}
    591599
     
    596604fillBufferPoll (struct rtems_termios_tty *tty)
    597605{
    598   unsigned char c;
    599   int n;
    600 
    601   if (tty->termios.c_lflag & ICANON) {
    602     for (;;) {
    603       n = (*tty->read)(tty->minor, &c);
    604       if (n < 0) {
    605         return RTEMS_UNSATISFIED;
    606       }
    607       else if (n == 0) {
    608         rtems_task_wake_after (1);
    609       }
    610       else {
    611         if  (siproc (c, tty))
    612           break;
    613       }
    614     }
    615   }
    616   else {
    617     rtems_interval then, now;
    618     if (!tty->termios.c_cc[VMIN] && tty->termios.c_cc[VTIME])
    619       rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &then);
    620     for (;;) {
    621       n = (*tty->read)(tty->minor, &c);
    622       if (n < 0) {
    623         return RTEMS_UNSATISFIED;
    624       }
    625       else if (n == 0) {
    626         if (tty->termios.c_cc[VMIN]) {
    627           if (tty->termios.c_cc[VTIME] && tty->ccount) {
    628             rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
    629             if ((now - then) > tty->vtimeTicks) {
    630               break;
    631             }
    632           }
    633         }
    634         else {
    635           if (!tty->termios.c_cc[VTIME])
    636             break;
    637           rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
    638           if ((now - then) > tty->vtimeTicks) {
    639             break;
    640           }
    641         }
    642         rtems_task_wake_after (1);
    643       }
    644       else {
    645         siproc (c, tty);
    646         if (tty->ccount >= tty->termios.c_cc[VMIN])
    647           break;
    648         if (tty->termios.c_cc[VMIN] && tty->termios.c_cc[VTIME])
    649           rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &then);
    650       }
    651     }
    652   }
    653   return RTEMS_SUCCESSFUL;
     606        unsigned char c;
     607        int n;
     608
     609        if (tty->termios.c_lflag & ICANON) {
     610                for (;;) {
     611                        n = (*tty->read)(tty->minor, &c);
     612                        if (n < 0) {
     613                                return RTEMS_UNSATISFIED;
     614                        }
     615                        else if (n == 0) {
     616                                rtems_task_wake_after (1);
     617                        }
     618                        else {
     619                                if  (siproc (c, tty))
     620                                        break;
     621                        }
     622                }
     623        }
     624        else {
     625                rtems_interval then, now;
     626                if (!tty->termios.c_cc[VMIN] && tty->termios.c_cc[VTIME])
     627                        rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &then);
     628                for (;;) {
     629                        n = (*tty->read)(tty->minor, &c);
     630                        if (n < 0) {
     631                                return RTEMS_UNSATISFIED;
     632                        }
     633                        else if (n == 0) {
     634                                if (tty->termios.c_cc[VMIN]) {
     635                                        if (tty->termios.c_cc[VTIME] && tty->ccount) {
     636                                                rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
     637                                                if ((now - then) > tty->vtimeTicks) {
     638                                                        break;
     639                                                }
     640                                        }
     641                                }
     642                                else {
     643                                        if (!tty->termios.c_cc[VTIME])
     644                                                break;
     645                                        rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &now);
     646                                        if ((now - then) > tty->vtimeTicks) {
     647                                                break;
     648                                        }
     649                                }
     650                                rtems_task_wake_after (1);
     651                        }
     652                        else {
     653                                siproc (c, tty);
     654                                if (tty->ccount >= tty->termios.c_cc[VMIN])
     655                                        break;
     656                                if (tty->termios.c_cc[VMIN] && tty->termios.c_cc[VTIME])
     657                                        rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &then);
     658                        }
     659                }
     660        }
     661        return RTEMS_SUCCESSFUL;
    654662}
    655663
     
    660668fillBufferQueue (struct rtems_termios_tty *tty)
    661669{
    662   rtems_interval timeout = tty->rawMessageFirstTimeout;
    663   rtems_status_code sc;
    664   rtems_unsigned8   c;
    665 
    666   for (;;) {
    667 
    668     /*
    669      * Read characters from raw queue
    670      */
    671     sc = rtems_semaphore_obtain (tty->rawInputSem,
    672               tty->rawMessageOptions,
    673               timeout);
    674     if (sc != RTEMS_SUCCESSFUL)
    675       break;
    676     Ring_buffer_Remove_character( &tty->rawInputBuffer, c );
    677 
    678    /*
    679     * Process characters read from raw queue
    680     */
    681     if (tty->termios.c_lflag & ICANON) {
    682       if  (siproc (c, tty))
    683         return RTEMS_SUCCESSFUL;
    684     }
    685     else {
    686       siproc (c, tty);
    687       if (tty->ccount >= tty->termios.c_cc[VMIN])
    688         return RTEMS_SUCCESSFUL;
    689     }
    690 
    691     timeout = tty->rawMessageTimeout;
    692   }
    693   return RTEMS_SUCCESSFUL;
     670        rtems_interval timeout = tty->rawBufSemaphoreFirstTimeout;
     671        rtems_status_code sc;
     672
     673        for (;;) {
     674                /*
     675                 * Process characters read from raw queue
     676                 */
     677                while (tty->rawBufHead != tty->rawBufTail) {
     678                        unsigned char c;
     679                        unsigned int newHead;
     680
     681                        newHead = (tty->rawBufHead + 1) % RAW_BUFFER_SIZE;
     682                        c = tty->rawBuf[newHead];
     683                        tty->rawBufHead = newHead;
     684                        if (tty->termios.c_lflag & ICANON) {
     685                                if  (siproc (c, tty))
     686                                        return RTEMS_SUCCESSFUL;
     687                        }
     688                        else {
     689                                siproc (c, tty);
     690                                if (tty->ccount >= tty->termios.c_cc[VMIN])
     691                                        return RTEMS_SUCCESSFUL;
     692                        }
     693                        timeout = tty->rawBufSemaphoreTimeout;
     694                }
     695
     696                /*
     697                 * Wait for characters
     698                 */
     699                sc = rtems_semaphore_obtain (tty->rawBufSemaphore,
     700                                                tty->rawBufSemaphoreOptions,
     701                                                timeout);
     702                if (sc != RTEMS_SUCCESSFUL)
     703                        break;
     704        }
     705        return RTEMS_SUCCESSFUL;
    694706}
    695707
     
    697709rtems_termios_read (void *arg)
    698710{
    699   rtems_libio_rw_args_t *args = arg;
    700   struct rtems_termios_tty *tty = args->iop->data1;
    701   unsigned32 count = args->count;
    702   unsigned8 *buffer = args->buffer;
    703   rtems_status_code sc;
    704 
    705   sc = rtems_semaphore_obtain (tty->isem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
    706   if (sc != RTEMS_SUCCESSFUL)
    707     return sc;
    708   if (tty->cindex == tty->ccount) {
    709     tty->cindex = tty->ccount = 0;
    710     tty->read_start_column = tty->column;
    711     if (tty->read)
    712       sc = fillBufferPoll (tty);
    713     else
    714       sc = fillBufferQueue (tty);
    715     if (sc != RTEMS_SUCCESSFUL)
    716       tty->cindex = tty->ccount = 0;
    717   }
    718   while (count && (tty->cindex < tty->ccount)) {
    719     *buffer++ = tty->cbuf[tty->cindex++];
    720     count--;
    721   }
    722   args->bytes_moved = args->count - count;
    723   rtems_semaphore_release (tty->isem);
    724   return sc;
     711        rtems_libio_rw_args_t *args = arg;
     712        struct rtems_termios_tty *tty = args->iop->data1;
     713        unsigned32 count = args->count;
     714        unsigned8 *buffer = args->buffer;
     715        rtems_status_code sc;
     716
     717        sc = rtems_semaphore_obtain (tty->isem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
     718        if (sc != RTEMS_SUCCESSFUL)
     719                return sc;
     720        if (tty->cindex == tty->ccount) {
     721                tty->cindex = tty->ccount = 0;
     722                tty->read_start_column = tty->column;
     723                if (tty->read)
     724                        sc = fillBufferPoll (tty);
     725                else
     726                        sc = fillBufferQueue (tty);
     727                if (sc != RTEMS_SUCCESSFUL)
     728                        tty->cindex = tty->ccount = 0;
     729        }
     730        while (count && (tty->cindex < tty->ccount)) {
     731                *buffer++ = tty->cbuf[tty->cindex++];
     732                count--;
     733        }
     734        args->bytes_moved = args->count - count;
     735        rtems_semaphore_release (tty->isem);
     736        return sc;
    725737}
    726738
     
    732744rtems_termios_enqueue_raw_characters (void *ttyp, char *buf, int len)
    733745{
    734   struct rtems_termios_tty *tty = ttyp;
    735 
    736   while (len) {
    737     if (Ring_buffer_Is_full(&tty->rawInputBuffer))
    738       break;
    739     Ring_buffer_Add_character(&tty->rawInputBuffer, *buf);
    740     if (rtems_semaphore_release(tty->rawInputSem) != RTEMS_SUCCESSFUL)
    741       break;
    742     len -= 1;
    743     buf += 1;
    744   }
    745 }
    746 
     746        struct rtems_termios_tty *tty = ttyp;
     747        unsigned int newTail;
     748
     749        while (len) {
     750                newTail = (tty->rawBufTail + 1) % RAW_BUFFER_SIZE;
     751                if (newTail == tty->rawBufHead) {
     752                        tty->rawBufDropped += len;
     753                        break;
     754                }
     755                tty->rawBuf[newTail] = *buf++;
     756                len--;
     757                tty->rawBufTail = newTail;
     758        }
     759        rtems_semaphore_release (tty->rawBufSemaphore);
     760}
     761
     762/*
     763 *  Reserve enough resources to at least open every physical device
     764 *  once.
     765 */
     766
     767void rtems_termios_reserve_resources(
     768  rtems_configuration_table *configuration,
     769  rtems_unsigned32           number_of_devices
     770)
     771{
     772  static int first_time = 1;
     773  rtems_api_configuration_table *rtems_config;
     774
     775  if (!configuration)
     776    rtems_fatal_error_occurred (0xFFF0F001);
     777
     778  rtems_config = configuration->RTEMS_api_configuration;
     779  if (!rtems_config)
     780    rtems_fatal_error_occurred (0xFFF0F002);
     781
     782  if (first_time)
     783    rtems_config->maximum_semaphores += 1;
     784
     785  first_time = 0;
     786  rtems_config->maximum_semaphores += (3 * number_of_devices);
     787}
Note: See TracChangeset for help on using the changeset viewer.