source: rtems/cpukit/libcsupport/src/termios.c @ 3ee825e8

4.104.114.84.95
Last change on this file since 3ee825e8 was 3ee825e8, checked in by Joel Sherrill <joel.sherrill@…>, on 10/23/97 at 15:00:32

fixed comment

  • Property mode set to 100644
File size: 17.4 KB
RevLine 
[55e1322]1/*
2 * TERMIOS serial line support
3 *
4 *  Author:
5 *    W. Eric Norum
6 *    Saskatchewan Accelerator Laboratory
7 *    University of Saskatchewan
8 *    Saskatoon, Saskatchewan, CANADA
9 *    eric@skatter.usask.ca
10 *
11 *  The license and distribution terms for this file may be
12 *  found in the file LICENSE in this distribution or at
13 *  http://www.OARcorp.com/rtems/license.html.
14 *
15 *  $Id$
16 */
17
18#include <rtems.h>
19#include <rtems/libio.h>
20#include <ctype.h>
21#include <errno.h>
22#include <stdio.h>
23#include <stdlib.h>
24#include <termios.h>
25#include <unistd.h>
26
27/*
28 * The size of the cooked buffer
29 */
[118a812]30#define CBUFSIZE        256
31
32/*
33 * The size of the raw input message queue
34 */
35#define RAW_BUFFER_SIZE 128
[55e1322]36
37/*
38 * Variables associated with each termios instance.
39 * One structure for each hardware I/O device.
40 */
41struct rtems_termios_tty {
[118a812]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);
[55e1322]102};
103static struct rtems_termios_tty *ttyHead, *ttyTail;
104static rtems_id ttyMutex;
105
106void
107rtems_termios_initialize (void)
108{
[118a812]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        }
[55e1322]124}
[118a812]125       
[55e1322]126/*
127 * Open a termios device
128 */
129rtems_status_code
130rtems_termios_open (
131  rtems_device_major_number  major,
132  rtems_device_minor_number  minor,
133  void                      *arg,
134  int                      (*deviceFirstOpen)(int major, int minor, void *arg),
135  int                      (*deviceLastClose)(int major, int minor, void *arg),
[118a812]136  int                      (*deviceRead)(int minor, char *buf),
[55e1322]137  int                      (*deviceWrite)(int minor, char *buf, int len)
138  )
139{
[118a812]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;
[55e1322]253}
254
255rtems_status_code
256rtems_termios_close (void *arg)
257{
[118a812]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;
[55e1322]284}
285
286rtems_status_code
287rtems_termios_ioctl (void *arg)
288{
[118a812]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;
[55e1322]339}
340
341/*
342 * Handle output processing
343 */
344static void
345oproc (unsigned char c, struct rtems_termios_tty *tty)
346{
[118a812]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);
[55e1322]396}
397
398rtems_status_code
399rtems_termios_write (void *arg)
400{
[118a812]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;
[55e1322]423}
424
425/*
426 * Echo a typed character
427 */
428static void
429echo (unsigned char c, struct rtems_termios_tty *tty)
430{
[118a812]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        }
[55e1322]442}
443
444/*
445 * Erase a character or line
446 * FIXME: Needs support for WERASE and ECHOPRT.
447 * FIXME: Some of the tests should check for IEXTEN, too.
448 */
449static void
450erase (struct rtems_termios_tty *tty, int lineFlag)
451{
[118a812]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        }
[55e1322]519}
520
521/*
522 * Process a single input character
523 */
524static int
525iproc (unsigned char c, struct rtems_termios_tty *tty)
526{
[118a812]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;
[55e1322]576}
577
578/*
579 * Process input character, with semaphore.
580 */
581static int
582siproc (unsigned char c, struct rtems_termios_tty *tty)
583{
[118a812]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;
[55e1322]598}
599
600/*
601 * Fill the input buffer by polling the device
602 */
603static rtems_status_code
604fillBufferPoll (struct rtems_termios_tty *tty)
605{
[118a812]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;
[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.