source: rtems/c/src/lib/libc/termios.c @ 5a5bd13b

4.104.114.84.95
Last change on this file since 5a5bd13b was 5a5bd13b, checked in by Joel Sherrill <joel.sherrill@…>, on 10/24/97 at 19:29:01

added katsutoshi Shibuya

  • Property mode set to 100644
File size: 17.4 KB
RevLine 
[55e1322]1/*
2 * TERMIOS serial line support
3 *
[5a5bd13b]4 *  Authors:
[55e1322]5 *    W. Eric Norum
6 *    Saskatchewan Accelerator Laboratory
7 *    University of Saskatchewan
8 *    Saskatoon, Saskatchewan, CANADA
9 *    eric@skatter.usask.ca
10 *
[5a5bd13b]11 *    AND
12 *
13 *    Katsutoshi Shibuya
14 *    BU Denken Co.,Ltd.
15 *    Sapporo, JAPAN
16 *    shibuya@mxb.meshnet.or.jp
17 *
[55e1322]18 *  The license and distribution terms for this file may be
19 *  found in the file LICENSE in this distribution or at
20 *  http://www.OARcorp.com/rtems/license.html.
21 *
22 *  $Id$
23 */
24
25#include <rtems.h>
26#include <rtems/libio.h>
27#include <ctype.h>
28#include <errno.h>
29#include <stdio.h>
30#include <stdlib.h>
31#include <termios.h>
32#include <unistd.h>
33
34/*
35 * The size of the cooked buffer
36 */
[118a812]37#define CBUFSIZE        256
38
39/*
40 * The size of the raw input message queue
41 */
42#define RAW_BUFFER_SIZE 128
[55e1322]43
44/*
45 * Variables associated with each termios instance.
46 * One structure for each hardware I/O device.
47 */
48struct rtems_termios_tty {
[118a812]49        /*
50         * Linked-list of active TERMIOS devices
51         */
52        struct rtems_termios_tty        *forw;
53        struct rtems_termios_tty        *back;
54
55        /*
56         * How many times has this device been opened
57         */
58        int             refcount;
59
60        /*
61         * This device
62         */
63        rtems_device_major_number       major;
64        rtems_device_major_number       minor;
65
66        /*
67         * Mutual-exclusion semaphores
68         */
69        rtems_id        isem;
70        rtems_id        osem;
71
72        /*
73         * The canonical (cooked) character buffer
74         */
75        char            cbuf[CBUFSIZE];
76        int             ccount;
77        int             cindex;
78
79        /*
80         * Keep track of cursor (printhead) position
81         */
82        int             column;
83        int             read_start_column;
84
85        /*
86         * The ioctl settings
87         */
88        struct termios  termios;
89        rtems_interval  vtimeTicks;
90
91        /*
92         * Raw character buffer
93         */
94        volatile char           rawBuf[RAW_BUFFER_SIZE];
95        volatile unsigned int   rawBufHead;
96        volatile unsigned int   rawBufTail;
97        rtems_id                rawBufSemaphore;
98        rtems_unsigned32        rawBufSemaphoreOptions;
99        rtems_interval          rawBufSemaphoreTimeout;
100        rtems_interval          rawBufSemaphoreFirstTimeout;
101        unsigned int            rawBufDropped;  /* Statistics */
102
103        /*
104         * Callbacks to device-specific routines
105         */
106        int             (*lastClose)(int major, int minor, void *arg);
[51eb8d5]107        int             (*read)(int minor);
[118a812]108        int             (*write)(int minor, char *buf, int len);
[55e1322]109};
110static struct rtems_termios_tty *ttyHead, *ttyTail;
111static rtems_id ttyMutex;
112
113void
114rtems_termios_initialize (void)
115{
[118a812]116        rtems_status_code sc;
117
118        /*
119         * Create the mutex semaphore for the tty list
120         */
121        if (!ttyMutex) {
122                sc = rtems_semaphore_create (
123                        rtems_build_name ('T', 'R', 'm', 'i'),
124                        1,
125                        RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
126                        RTEMS_NO_PRIORITY,
127                        &ttyMutex);
128                if (sc != RTEMS_SUCCESSFUL)
129                        rtems_fatal_error_occurred (sc);
130        }
[55e1322]131}
[118a812]132       
[55e1322]133/*
134 * Open a termios device
135 */
136rtems_status_code
137rtems_termios_open (
138  rtems_device_major_number  major,
139  rtems_device_minor_number  minor,
140  void                      *arg,
141  int                      (*deviceFirstOpen)(int major, int minor, void *arg),
142  int                      (*deviceLastClose)(int major, int minor, void *arg),
[51eb8d5]143  int                      (*deviceRead)(int minor),
[55e1322]144  int                      (*deviceWrite)(int minor, char *buf, int len)
145  )
146{
[118a812]147        rtems_status_code sc;
148        rtems_libio_open_close_args_t *args = arg;
149        struct rtems_termios_tty *tty;
150
151        /*
152         * See if the device has already been opened
153         */
154        sc = rtems_semaphore_obtain (ttyMutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
155        if (sc != RTEMS_SUCCESSFUL)
156                return sc;
157        for (tty = ttyHead ; tty != NULL ; tty = tty->forw) {
158                if ((tty->major == major) && (tty->minor == minor))
159                        break;
160        }
161        if (tty == NULL) {
162                static char c = 'a';
163
164                /*
165                 * Create a new device
166                 */
167                tty = malloc (sizeof (struct rtems_termios_tty));
168                if (tty == NULL) {
169                        rtems_semaphore_release (ttyMutex);
170                        return RTEMS_NO_MEMORY;
171                }
172                tty->forw = ttyHead;
173                ttyHead = tty;
174                tty->back = NULL;
175                if (ttyTail == NULL)
176                        ttyTail = tty;
177
178                /*
179                 * Set up mutex semaphores
180                 */
181                sc = rtems_semaphore_create (
182                        rtems_build_name ('T', 'R', 'i', c),
183                        1,
184                        RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
185                        RTEMS_NO_PRIORITY,
186                        &tty->isem);
187                if (sc != RTEMS_SUCCESSFUL)
188                        rtems_fatal_error_occurred (sc);
189                sc = rtems_semaphore_create (
190                        rtems_build_name ('T', 'R', 'o', c),
191                        1,
192                        RTEMS_BINARY_SEMAPHORE | RTEMS_INHERIT_PRIORITY | RTEMS_PRIORITY,
193                        RTEMS_NO_PRIORITY,
194                        &tty->osem);
195                if (sc != RTEMS_SUCCESSFUL)
196                        rtems_fatal_error_occurred (sc);
197
198                /*
199                 * Set callbacks
200                 */
201                tty->write = deviceWrite;
202                tty->lastClose = deviceLastClose;
203                if ((tty->read = deviceRead) == NULL) {
204                        sc = rtems_semaphore_create (
205                                rtems_build_name ('T', 'R', 'r', c),
206                                0,
207                                RTEMS_COUNTING_SEMAPHORE | RTEMS_PRIORITY,
208                                RTEMS_NO_PRIORITY,
209                                &tty->rawBufSemaphore);
210                        if (sc != RTEMS_SUCCESSFUL)
211                                rtems_fatal_error_occurred (sc);
212                        tty->rawBufHead = 0;
213                        tty->rawBufTail = 0;
214                }
215
216                /*
217                 * Initialize variables
218                 */
219                tty->column = 0;
220                tty->cindex = tty->ccount = 0;
221
222                /*
223                 * Set default parameters
224                 */
225                tty->termios.c_iflag = BRKINT | ICRNL | IXON | IMAXBEL;
226                tty->termios.c_oflag = OPOST | ONLCR | XTABS;
227                tty->termios.c_cflag = B9600 | CS8 | CREAD;
228                tty->termios.c_lflag = ISIG | ICANON | IEXTEN | ECHO | ECHOK | ECHOE | ECHOCTL;
229                tty->termios.c_cc[VINTR] = '\003';
230                tty->termios.c_cc[VQUIT] = '\034';
231                tty->termios.c_cc[VERASE] = '\177';
232                tty->termios.c_cc[VKILL] = '\025';
233                tty->termios.c_cc[VEOF] = '\004';
234                tty->termios.c_cc[VEOL] = '\000';
235                tty->termios.c_cc[VEOL2] = '\000';
236                tty->termios.c_cc[VSTART] = '\021';
237                tty->termios.c_cc[VSTOP] = '\023';
238                tty->termios.c_cc[VSUSP] = '\032';
239                tty->termios.c_cc[VREPRINT] = '\022';
240                tty->termios.c_cc[VDISCARD] = '\017';
241                tty->termios.c_cc[VWERASE] = '\027';
242                tty->termios.c_cc[VLNEXT] = '\026';
243
244                /*
245                 * Device-specific open
246                 */
247                if (deviceFirstOpen)
248                        (*deviceFirstOpen) (major, minor, arg);
249
250                /*
251                 * Bump name characer
252                 */
253                if (c++ == 'z')
254                        c = 'a';
255        }
256        tty->refcount++;
257        args->iop->data1 = tty;
258        rtems_semaphore_release (ttyMutex);
259        return RTEMS_SUCCESSFUL;
[55e1322]260}
261
262rtems_status_code
263rtems_termios_close (void *arg)
264{
[118a812]265        rtems_libio_open_close_args_t *args = arg;
266        struct rtems_termios_tty *tty = args->iop->data1;
267        rtems_status_code sc;
268
269        sc = rtems_semaphore_obtain (ttyMutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
270        if (sc != RTEMS_SUCCESSFUL)
271                rtems_fatal_error_occurred (sc);
272        if (--tty->refcount == 0) {
273                if (tty->lastClose)
274                         (*tty->lastClose) (tty->major, tty->minor, arg);
275                if (tty->forw == NULL)
276                        ttyTail = tty->back;
277                else
278                        tty->forw->back = tty->back;
279                if (tty->back == NULL)
280                        ttyHead = tty->forw;
281                else
282                        tty->back->forw = tty->forw;
283                rtems_semaphore_delete (tty->isem);
284                rtems_semaphore_delete (tty->osem);
285                if (tty->read == NULL)
286                        rtems_semaphore_delete (tty->rawBufSemaphore);
287                free (tty);
288        }
289        rtems_semaphore_release (ttyMutex);
290        return RTEMS_SUCCESSFUL;
[55e1322]291}
292
293rtems_status_code
294rtems_termios_ioctl (void *arg)
295{
[118a812]296        rtems_libio_ioctl_args_t *args = arg;
297        struct rtems_termios_tty *tty = args->iop->data1;
298        rtems_status_code sc;
299
300        sc = rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
301        if (sc != RTEMS_SUCCESSFUL)
302                return sc;
303        switch (args->command) {
304        default:
305                sc = RTEMS_INVALID_NUMBER;
306                break;
307
308        case RTEMS_IO_GET_ATTRIBUTES:
309                *(struct termios *)args->buffer = tty->termios;
310                break;
311
312        case RTEMS_IO_SET_ATTRIBUTES:
313                tty->termios = *(struct termios *)args->buffer;
314                if (tty->termios.c_lflag & ICANON) {
315                        tty->rawBufSemaphoreOptions = RTEMS_WAIT;
316                        tty->rawBufSemaphoreTimeout = RTEMS_NO_TIMEOUT;
317                        tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
318                }
319                else {
320                        rtems_interval ticksPerSecond;
321                        rtems_clock_get (RTEMS_CLOCK_GET_TICKS_PER_SECOND, &ticksPerSecond);
322                        tty->vtimeTicks = tty->termios.c_cc[VTIME] * ticksPerSecond / 10;
323                        if (tty->termios.c_cc[VTIME]) {
324                                tty->rawBufSemaphoreOptions = RTEMS_WAIT;
325                                tty->rawBufSemap`oreTimeout = tty->vtimeTicks;
326                                if (tty->termios.c_cc[VMIN])
327                                        tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
328                                else
329                                        tty->rawBufSemaphoreFirstTimeout = tty->vtimeTicks;
330                        }
331                        else {
332                                if (tty->termios.c_cc[VMIN]) {
333                                        tty->rawBufSemaphoreOptions = RTEMS_WAIT;
334                                        tty->rawBufSemaphoreTimeout = RTEMS_NO_TIMEOUT;
335                                        tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
336                                }
337                                else {
338                                        tty->rawBufSemaphoreOptions = RTEMS_NO_WAIT;
339                                }
340                        }
341                }
342                break;
343        }
344        rtems_semaphore_release (tty->osem);
345        return sc;
[55e1322]346}
347
348/*
349 * Handle output processing
350 */
351static void
352oproc (unsigned char c, struct rtems_termios_tty *tty)
353{
[118a812]354        int     i;
355
356        if (tty->termios.c_oflag & OPOST) {
357                switch (c) {
358                case '\n':
359                        if (tty->termios.c_oflag & ONLRET)
360                                tty->column = 0;
361                        if (tty->termios.c_oflag & ONLCR) {
362                                (*tty->write)(tty->minor, "\r", 1);
363                                tty->column = 0;
364                        }
365                        break;
366
367                case '\r':
368                        if ((tty->termios.c_oflag & ONOCR) && (tty->column == 0))
369                                return;
370                        if (tty->termios.c_oflag & OCRNL) {
371                                c = '\n';
372                                if (tty->termios.c_oflag & ONLRET)
373                                        tty->column = 0;
374                                break;
375                        }
376                        tty->column = 0;
377                        break;
378
379                case '\t':
380                        i = 8 - (tty->column & 7);
381                        if ((tty->termios.c_oflag & TABDLY) == XTABS) {
382                                tty->column += i;
383                                (*tty->write)(tty->minor,  "        ",  i);
384                                return;
385                        }
386                        tty->column += i;
387                        break;
388
389                case '\b':
390                        if (tty->column > 0)
391                                tty->column--;
392                        break;
393
394                default:
395                        if (tty->termios.c_oflag & OLCUC)
396                                c = toupper(c);
397                        if (!iscntrl(c))
398                                tty->column++;
399                        break;
400                }
401        }
402        (*tty->write)(tty->minor, &c, 1);
[55e1322]403}
404
405rtems_status_code
406rtems_termios_write (void *arg)
407{
[118a812]408        rtems_libio_rw_args_t *args = arg;
409        struct rtems_termios_tty *tty = args->iop->data1;
410        rtems_status_code sc;
411
412        sc = rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
413        if (sc != RTEMS_SUCCESSFUL)
414                return sc;
415        if (tty->termios.c_oflag & OPOST) {
416                unsigned32 count = args->count;
417                unsigned8 *buffer = args->buffer;
418                while (count--)
419                        oproc (*buffer++, tty);
420                args->bytes_moved = args->count;
421        }
422        else {
423                if ((*tty->write)(tty->minor, args->buffer, args->count) < 0)
424                        sc = RTEMS_UNSATISFIED;
425                else
426                        args->bytes_moved = args->count;
427        }
428        rtems_semaphore_release (tty->osem);
429        return sc;
[55e1322]430}
431
432/*
433 * Echo a typed character
434 */
435static void
436echo (unsigned char c, struct rtems_termios_tty *tty)
437{
[118a812]438        if ((tty->termios.c_lflag & ECHOCTL) && iscntrl(c) && (c != '\t') && (c != '\n')) {
439                char echobuf[2];
440
441                echobuf[0] = '^';
442                echobuf[1] = c ^ 0x40;
443                (*tty->write)(tty->minor, echobuf, 2);
444                tty->column += 2;
445        }
446        else {
447                oproc (c, tty);
448        }
[55e1322]449}
450
451/*
452 * Erase a character or line
453 * FIXME: Needs support for WERASE and ECHOPRT.
454 * FIXME: Some of the tests should check for IEXTEN, too.
455 */
456static void
457erase (struct rtems_termios_tty *tty, int lineFlag)
458{
[118a812]459        if (tty->ccount == 0)
460                return;
461        if (lineFlag) {
462                if (!(tty->termios.c_lflag & ECHO)) {
463                        tty->ccount = 0;
464                        return;
465                }
466                if (!(tty->termios.c_lflag & ECHOE)) {
467                        tty->ccount = 0;
468                        echo (tty->termios.c_cc[VKILL], tty);
469                        if (tty->termios.c_lflag & ECHOK)
470                                echo ('\n', tty);
471                        return;
472                }
473        }
474        while (tty->ccount) {
475                unsigned char c = tty->cbuf[--tty->ccount];
476
477                if (tty->termios.c_lflag & ECHO) {
478                        if (!lineFlag && !(tty->termios.c_lflag & ECHOE)) {
479                                echo (tty->termios.c_cc[VERASE], tty);
480                        }
481                        else if (c == '\t') {
482                                int col = tty->read_start_column;
483                                int i = 0;
484
485                                /*
486                                 * Find the character before the tab
487                                 */
488                                while (i != tty->ccount) {
489                                        c = tty->cbuf[i++];
490                                        if (c == '\t') {
491                                                col = (col | 7) + 1;
492                                        }
493                                        else if (iscntrl (c)) {
494                                                if (tty->termios.c_lflag & ECHOCTL)
495                                                        col += 2;
496                                        }
497                                        else {
498                                                col++;
499                                        }
500                                }
501
502                                /*
503                                 * Back up over the tab
504                                 */
505                                while (tty->column > col) {
506                                        (*tty->write)(tty->minor, "\b", 1);
507                                        tty->column--;
508                                }
509                        }
510                        else {
511                                if (iscntrl (c) && (tty->termios.c_lflag & ECHOCTL)) {
512                                        (*tty->write)(tty->minor, "\b \b", 3);
513                                        if (tty->column)
514                                                tty->column--;
515                                }
516                                if (!iscntrl (c) || (tty->termios.c_lflag & ECHOCTL)) {
517                                        (*tty->write)(tty->minor, "\b \b", 3);
518                                        if (tty->column)
519                                                tty->column--;
520                                }
521                        }
522                }
523                if (!lineFlag)
524                        break;
525        }
[55e1322]526}
527
528/*
529 * Process a single input character
530 */
531static int
532iproc (unsigned char c, struct rtems_termios_tty *tty)
533{
[118a812]534        if (tty->termios.c_iflag & ISTRIP)
535                c &= 0x7f;
536        if (tty->termios.c_iflag & IUCLC)
537                c = tolower (c);
538        if (c == '\r') {
539                if (tty->termios.c_iflag & IGNCR)
540                        return 0;
541                if (tty->termios.c_iflag & ICRNL)
542                        c = '\n';
543        }
544        else if ((c == '\n') && (tty->termios.c_iflag & INLCR)) {
545                c = '\r';
546        }
547        if ((c != '\0') && (tty->termios.c_lflag & ICANON)) {
548                if (c == tty->termios.c_cc[VERASE]) {
549                        erase (tty, 0);
550                        return 0;
551                }
552                else if (c == tty->termios.c_cc[VKILL]) {
553                        erase (tty, 1);
554                        return 0;
555                }
556                else if (c == tty->termios.c_cc[VEOF]) {
557                        return 1;
558                }
559                else if (c == '\n') {
560                        if (tty->termios.c_lflag & (ECHO | ECHONL))
561                                echo (c, tty);
562                        tty->cbuf[tty->ccount++] = c;
563                        return 1;
564                }
565                else if ((c == tty->termios.c_cc[VEOL])
566                      || (c == tty->termios.c_cc[VEOL2])) {
567                        if (tty->termios.c_lflag & ECHO)
568                                echo (c, tty);
569                        tty->cbuf[tty->ccount++] = c;
570                        return 1;
571                }
572        }
573
574        /*
575         * FIXME: Should do IMAXBEL handling somehow
576         */
577        if (tty->ccount < (CBUFSIZE-1)) {
578                if (tty->termios.c_lflag & ECHO)
579                        echo (c, tty);
580                tty->cbuf[tty->ccount++] = c;
581        }
582        return 0;
[55e1322]583}
584
585/*
586 * Process input character, with semaphore.
587 */
588static int
589siproc (unsigned char c, struct rtems_termios_tty *tty)
590{
[118a812]591        int i;
592
593        /*
594         * Obtain output semaphore if character will be echoed
595         */
596        if (tty->termios.c_lflag & (ECHO|ECHOE|ECHOK|ECHONL|ECHOPRT|ECHOCTL|ECHOKE)) {
597                rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
598                i = iproc (c, tty);
599                rtems_semaphore_release (tty->osem);
600        }
601        else {
602                i = iproc (c, tty);
603        }
604        return i;
[55e1322]605}
606
607/*
608 * Fill the input buffer by polling the device
609 */
610static rtems_status_code
611fillBufferPoll (struct rtems_termios_tty *tty)
612{
[118a812]613        int n;
614
615        if (tty->termios.c_lflag & ICANON) {
616                for (;;) {
[51eb8d5]617                        n = (*tty->read)(tty->minor);
[118a812]618                        if (n < 0) {
619                                rtems_task_wake_after (1);
620                        }
621                        else {
[51eb8d5]622                                if  (siproc (n, tty))
[118a812]623                                        break;
624                        }
625                }
626        }
627        else {
628                rtems_interval then, now;
629                if (!tty->termios.c_cc[VMIN] && tty->termios.c_cc[VTIME])
630                        rtems_clock_get (RTEMS_CLOCK_GET_TICKS_SINCE_BOOT, &then);
631                for (;;) {
[51eb8d5]632                        n = (*tty->read)(tty->minor);
[118a812]633                        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 {
[51eb8d5]653                                siproc (n, tty);
[118a812]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;
[55e1322]662}
663
664/*
665 * Fill the input buffer from the raw input queue
666 */
667static rtems_status_code
668fillBufferQueue (struct rtems_termios_tty *tty)
669{
[118a812]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;
[55e1322]706}
707
708rtems_status_code
709rtems_termios_read (void *arg)
710{
[118a812]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;
[55e1322]737}
738
739/*
740 * Place characters on raw queue.
741 * NOTE: This routine runs in the context of the device interrupt handler.
742 */
743void
744rtems_termios_enqueue_raw_characters (void *ttyp, char *buf, int len)
745{
[118a812]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);
[55e1322]760}
761
[118a812]762/*
[3ee825e8]763 *  Reserve enough resources to open every physical device once.
[118a812]764 */
765
766void rtems_termios_reserve_resources(
767  rtems_configuration_table *configuration,
768  rtems_unsigned32           number_of_devices
769)
770{
771  static int first_time = 1;
772  rtems_api_configuration_table *rtems_config;
773
774  if (!configuration)
775    rtems_fatal_error_occurred (0xFFF0F001);
776
777  rtems_config = configuration->RTEMS_api_configuration;
778  if (!rtems_config)
779    rtems_fatal_error_occurred (0xFFF0F002);
780
781  if (first_time)
782    rtems_config->maximum_semaphores += 1;
783
784  first_time = 0;
785  rtems_config->maximum_semaphores += (3 * number_of_devices);
786}
Note: See TracBrowser for help on using the repository browser.