source: rtems/bsps/shared/grlib/uart/apbuart_cons.c @ 411c297

5
Last change on this file since 411c297 was 411c297, checked in by Jiri Gaisler <jiri@…>, on 01/18/19 at 10:24:18

grlib: make apbuart driver independent of bsp

Update #3678.

  • Property mode set to 100644
File size: 18.7 KB
Line 
1/*  This file contains the driver for the GRLIB APBUART serial port. The driver
2 *  is implemented by using the cons.c console layer. Interrupt/Polling/Task
3 *  driven mode can be configured using driver resources:
4 *
5 *  - mode   (0=Polling, 1=Interrupt, 2=Task-Driven-Interrupt Mode)
6 *  - syscon (0=Force not Ssystem Console, 1=Suggest System Console)
7 *
8 *  The BSP define APBUART_INFO_AVAIL in order to add the info routine
9 *  used for debugging.
10 *
11 *  COPYRIGHT (c) 2010.
12 *  Cobham Gaisler AB.
13 *
14 *  The license and distribution terms for this file may be
15 *  found in the file LICENSE in this distribution or at
16 *  http://www.rtems.org/license/LICENSE.
17 */
18
19/******************* Driver manager interface ***********************/
20#include <bsp.h>
21#include <stdlib.h>
22#include <assert.h>
23#include <rtems/bspIo.h>
24#include <string.h>
25#include <stdio.h>
26
27#include <drvmgr/drvmgr.h>
28#include <grlib/ambapp_bus.h>
29#include <grlib/apbuart.h>
30#include <grlib/ambapp.h>
31#include <grlib/grlib.h>
32#include <grlib/cons.h>
33#include <rtems/termiostypes.h>
34#include <grlib/apbuart_cons.h>
35
36/*#define DEBUG 1  */
37
38#ifdef DEBUG
39#define DBG(x...) printk(x)
40#else
41#define DBG(x...)
42#endif
43
44/* LEON3 Low level transmit/receive functions provided by debug-uart code */
45#ifdef LEON3
46extern struct apbuart_regs *leon3_debug_uart; /* The debug UART */
47#endif
48
49/* Probed hardware capabilities */
50enum {
51        CAP_FIFO = 0x01, /* FIFO available */
52        CAP_DI   = 0x02, /* RX delayed interrupt available */
53};
54struct apbuart_priv {
55        struct console_dev condev;
56        struct drvmgr_dev *dev;
57        struct apbuart_regs *regs;
58        struct rtems_termios_tty *tty;
59        char devName[32];
60        volatile int sending;
61        int mode;
62        int cap;
63};
64
65/* Getters for different interfaces. It happens to be just casting which we do
66 * in one place to avoid getting cast away. */
67static struct console_dev *base_get_condev(rtems_termios_device_context *base)
68{
69        return (struct console_dev *) base;
70}
71
72static struct apbuart_priv *condev_get_priv(struct console_dev *condev)
73{
74        return (struct apbuart_priv *) condev;
75}
76
77static struct apbuart_priv *base_get_priv(rtems_termios_device_context *base)
78{
79        return condev_get_priv(base_get_condev(base));
80}
81
82/* TERMIOS Layer Callback functions */
83static bool first_open(
84  rtems_termios_tty *tty,
85  rtems_termios_device_context *base,
86  struct termios *term,
87  rtems_libio_open_close_args_t *args
88);
89static void last_close(
90  rtems_termios_tty *tty,
91  rtems_termios_device_context *base,
92  rtems_libio_open_close_args_t *args
93);
94static void write_interrupt(
95  rtems_termios_device_context *base,
96  const char *buf,
97  size_t len
98);
99static bool set_attributes(
100        rtems_termios_device_context *base,
101        const struct termios *t
102);
103static void get_attributes(
104        rtems_termios_device_context *base,
105        struct termios *t
106);
107static int read_polled(rtems_termios_device_context *base);
108static int read_task(rtems_termios_device_context *base);
109static void write_polled(
110  rtems_termios_device_context *base,
111  const char *buf,
112  size_t len
113);
114
115static void apbuart_cons_isr(void *arg);
116int apbuart_get_baud(struct apbuart_priv *uart);
117
118int apbuart_init1(struct drvmgr_dev *dev);
119#ifdef APBUART_INFO_AVAIL
120static int apbuart_info(
121        struct drvmgr_dev *dev,
122        void (*print_line)(void *p, char *str),
123        void *p, int, char *argv[]);
124#define APBUART_INFO_FUNC apbuart_info
125#else
126#define APBUART_INFO_FUNC NULL
127#endif
128
129struct drvmgr_drv_ops apbuart_ops =
130{
131        .init = {apbuart_init1, NULL, NULL, NULL},
132        .remove = NULL,
133        .info = APBUART_INFO_FUNC
134};
135
136static struct amba_dev_id apbuart_ids[] =
137{
138        {VENDOR_GAISLER, GAISLER_APBUART},
139        {0, 0}          /* Mark end of table */
140};
141
142static struct amba_drv_info apbuart_drv_info =
143{
144        {
145                DRVMGR_OBJ_DRV,                         /* Driver */
146                NULL,                                   /* Next driver */
147                NULL,                                   /* Device list */
148                DRIVER_AMBAPP_GAISLER_APBUART_ID,       /* Driver ID */
149                "APBUART_DRV",                          /* Driver Name */
150                DRVMGR_BUS_TYPE_AMBAPP,                 /* Bus Type */
151                &apbuart_ops,
152                NULL,                                   /* Funcs */
153                0,                                      /* No devices yet */
154                sizeof(struct apbuart_priv),            /*DrvMgr alloc private*/
155        },
156        &apbuart_ids[0]
157};
158
159void apbuart_cons_register_drv (void)
160{
161        DBG("Registering APBUART Console driver\n");
162        drvmgr_drv_register(&apbuart_drv_info.general);
163}
164
165static const rtems_termios_device_handler handler_interrupt = {
166        .first_open     = first_open,
167        .last_close     = last_close,
168        .write          = write_interrupt,
169        .set_attributes = set_attributes,
170        .mode           = TERMIOS_IRQ_DRIVEN
171};
172
173static const rtems_termios_device_handler handler_task = {
174        .first_open     = first_open,
175        .last_close     = last_close,
176        .poll_read      = read_task,
177        .write          = write_interrupt,
178        .set_attributes = set_attributes,
179        .mode           = TERMIOS_TASK_DRIVEN
180};
181
182static const rtems_termios_device_handler handler_polled = {
183        .first_open     = first_open,
184        .last_close     = last_close,
185        .poll_read      = read_polled,
186        .write          = write_polled,
187        .set_attributes = set_attributes,
188        .mode           = TERMIOS_POLLED
189};
190
191/*
192 * APBUART hardware instantiation is flexible. Probe features here and driver
193 * can select appropriate routines for the hardware. probecap() return value
194 * is a CAP_ bitmask.
195 */
196static int probecap(struct apbuart_regs *regs)
197{
198        int cap = 0;
199
200        /* Probe FIFO */
201        if (regs->ctrl & APBUART_CTRL_FA) {
202                cap |= CAP_FIFO;
203
204                /* Probe RX delayed interrupt */
205                regs->ctrl |= APBUART_CTRL_DI;
206                if (regs->ctrl & APBUART_CTRL_DI) {
207                        regs->ctrl &= ~APBUART_CTRL_DI;
208                        cap |= CAP_DI;
209                }
210        }
211
212        return cap;
213}
214
215int apbuart_init1(struct drvmgr_dev *dev)
216{
217        struct apbuart_priv *priv;
218        struct amba_dev_info *ambadev;
219        struct ambapp_core *pnpinfo;
220        union drvmgr_key_value *value;
221        char prefix[32];
222        unsigned int db;
223        static int first_uart = 1;
224
225        /* The default operation in AMP is to use APBUART[0] for CPU[0],
226         * APBUART[1] for CPU[1] and so on. The remaining UARTs is not used
227         * since we don't know how many CPU-cores there are. Note this only
228         * affects the on-chip amba bus (the root bus). The user can override
229         * the default resource sharing by defining driver resources for the
230         * APBUART devices on each AMP OS instance.
231         */
232#if defined(RTEMS_MULTIPROCESSING) && defined(LEON3)
233        if (drvmgr_on_rootbus(dev) && dev->minor_drv != LEON3_Cpu_Index &&
234            drvmgr_keys_get(dev, NULL) != 0) {
235                /* User hasn't configured on-chip APBUART, leave it untouched */
236                return DRVMGR_EBUSY;
237        }
238#endif
239
240        DBG("APBUART[%d] on bus %s\n", dev->minor_drv, dev->parent->dev->name);
241        /* Private data was allocated and zeroed by driver manager */
242        priv = dev->priv;
243        if (!priv)
244                return DRVMGR_NOMEM;
245        priv->dev = dev;
246
247        /* Get device information from AMBA PnP information */
248        ambadev = (struct amba_dev_info *)priv->dev->businfo;
249        if (ambadev == NULL)
250                return -1;
251        pnpinfo = &ambadev->info;
252        priv->regs = (struct apbuart_regs *)pnpinfo->apb_slv->start;
253
254        /* Clear HW regs, leave baudrate register as it is */
255        priv->regs->status = 0;
256
257        /* leave Transmitter/receiver if this is the RTEMS debug UART (assume
258         * it has been setup by boot loader).
259         */
260        db = 0;
261#ifdef LEON3
262        if (priv->regs == leon3_debug_uart) {
263                db = priv->regs->ctrl & (APBUART_CTRL_RE |
264                                        APBUART_CTRL_TE |
265                                        APBUART_CTRL_PE |
266                                        APBUART_CTRL_PS);
267        }
268#endif
269        /* Let UART debug tunnelling be untouched if Flow-control is set.
270         *
271         * With old APBUARTs debug is enabled by setting LB and FL, since LB or
272         * DB are not reset we can not trust them. However since FL is reset we
273         * guess that we are debugging if FL is already set, the debugger set
274         * either LB or DB depending on UART capabilities.
275         */
276        if (priv->regs->ctrl & APBUART_CTRL_FL) {
277                db |= priv->regs->ctrl & (APBUART_CTRL_DB |
278                      APBUART_CTRL_LB | APBUART_CTRL_FL);
279        }
280
281        priv->regs->ctrl = db;
282
283        priv->cap = probecap(priv->regs);
284
285        /* The system console and Debug console may depend on this device, so
286         * initialize it straight away.
287         *
288         * We default to have System Console on first APBUART, user may override
289         * this behaviour by setting the syscon option to 0.
290         */
291        if (drvmgr_on_rootbus(dev) && first_uart) {
292                priv->condev.flags = CONSOLE_FLAG_SYSCON;
293                first_uart = 0;
294        } else {
295                priv->condev.flags = 0;
296        }
297
298        value = drvmgr_dev_key_get(priv->dev, "syscon", DRVMGR_KT_INT);
299        if (value) {
300                if (value->i)
301                        priv->condev.flags |= CONSOLE_FLAG_SYSCON;
302                else
303                        priv->condev.flags &= ~CONSOLE_FLAG_SYSCON;
304        }
305
306        /* Select 0=Polled, 1=IRQ, 2=Task-Driven UART Mode */
307        value = drvmgr_dev_key_get(priv->dev, "mode", DRVMGR_KT_INT);
308        if (value)
309                priv->mode = value->i;
310        else
311                priv->mode = TERMIOS_POLLED;
312        /* TERMIOS device handlers */
313        if (priv->mode == TERMIOS_IRQ_DRIVEN) {
314                priv->condev.handler = &handler_interrupt;
315        } else if (priv->mode == TERMIOS_TASK_DRIVEN) {
316                priv->condev.handler = &handler_task;
317        } else {
318                priv->condev.handler = &handler_polled;
319        }
320
321        priv->condev.fsname = NULL;
322        /* Get Filesystem name prefix */
323        prefix[0] = '\0';
324        if (drvmgr_get_dev_prefix(dev, prefix)) {
325                /* Got special prefix, this means we have a bus prefix
326                 * And we should use our "bus minor"
327                 */
328                sprintf(priv->devName, "/dev/%sapbuart%d", prefix, dev->minor_bus);
329                priv->condev.fsname = priv->devName;
330        } else {
331                sprintf(priv->devName, "/dev/apbuart%d", dev->minor_drv);
332        }
333
334        /* Register it as a console device, the console driver will register
335         * a termios device as well
336         */
337        console_dev_register(&priv->condev);
338
339        return DRVMGR_OK;
340}
341
342#ifdef APBUART_INFO_AVAIL
343static int apbuart_info(
344        struct drvmgr_dev *dev,
345        void (*print_line)(void *p, char *str),
346        void *p, int argc, char *argv[])
347{
348        struct apbuart_priv *priv = dev->priv;
349        char *str1;
350        char buf[64];
351
352        if (dev->priv == NULL)
353                return -DRVMGR_EINVAL;
354
355        if (priv->mode == TERMIOS_POLLED)
356                str1 = "TERMIOS_POLLED";
357        else if (priv->mode == TERMIOS_IRQ_DRIVEN)
358                str1 = "TERMIOS_IRQ_DRIVEN";
359        else if (priv->mode == TERMIOS_TASK_DRIVEN)
360                str1 = "TERMIOS_TASK_DRIVEN";
361        else
362                str1 = "BAD MODE";
363
364        sprintf(buf, "UART Mode:   %s", str1);
365        print_line(p, buf);
366        if (priv->condev.fsname) {
367                sprintf(buf, "FS Name:     %s", priv->condev.fsname);
368                print_line(p, buf);
369        }
370        sprintf(buf, "STATUS REG:  0x%x", priv->regs->status);
371        print_line(p, buf);
372        sprintf(buf, "CTRL REG:    0x%x", priv->regs->ctrl);
373        print_line(p, buf);
374        sprintf(buf, "SCALER REG:  0x%x  baud rate %d",
375                                priv->regs->scaler, apbuart_get_baud(priv));
376        print_line(p, buf);
377
378        return DRVMGR_OK;
379}
380#endif
381
382static bool first_open(
383        rtems_termios_tty *tty,
384        rtems_termios_device_context *base,
385        struct termios *term,
386        rtems_libio_open_close_args_t *args
387)
388{
389        struct apbuart_priv *uart = base_get_priv(base);
390
391        uart->tty = tty;
392
393        /* Inherit UART hardware parameters from bootloader on system console */
394        if (uart->condev.flags & CONSOLE_FLAG_SYSCON_GRANT) {
395                get_attributes(base, term);
396                term->c_oflag |= ONLCR;
397                set_attributes(base, term);
398        }
399
400        /* Enable TX/RX */
401        uart->regs->ctrl |= APBUART_CTRL_RE | APBUART_CTRL_TE;
402
403        if (uart->mode != TERMIOS_POLLED) {
404                int ret;
405                uint32_t ctrl;
406
407                /* Register interrupt and enable it */
408                ret = drvmgr_interrupt_register(
409                        uart->dev, 0, uart->devName, apbuart_cons_isr, tty
410                );
411                if (ret) {
412                        return false;
413                }
414
415                uart->sending = 0;
416
417                /* Turn on RX interrupts */
418                ctrl = uart->regs->ctrl;
419                ctrl |= APBUART_CTRL_RI;
420                if (uart->cap & CAP_DI) {
421                        /* Use RX FIFO interrupt only if delayed interrupt available. */
422                        ctrl |= (APBUART_CTRL_DI | APBUART_CTRL_RF);
423                }
424                uart->regs->ctrl = ctrl;
425        }
426
427        return true;
428}
429
430static void last_close(
431        rtems_termios_tty *tty,
432        rtems_termios_device_context *base,
433        rtems_libio_open_close_args_t *args
434)
435{
436        struct apbuart_priv *uart = base_get_priv(base);
437        rtems_interrupt_lock_context lock_context;
438
439        if (uart->mode != TERMIOS_POLLED) {
440                /* Turn off RX interrupts */
441                rtems_termios_device_lock_acquire(base, &lock_context);
442                uart->regs->ctrl &=
443                        ~(APBUART_CTRL_DI | APBUART_CTRL_RI | APBUART_CTRL_RF);
444                rtems_termios_device_lock_release(base, &lock_context);
445
446                /**** Flush device ****/
447                while (uart->sending) {
448                        /* Wait until all data has been sent */
449                }
450                while (
451                        (uart->regs->ctrl & APBUART_CTRL_TE) &&
452                        !(uart->regs->status & APBUART_STATUS_TS)
453                ) {
454                        /* Wait until all data has left shift register */
455                }
456
457                /* Disable and unregister interrupt handler */
458                drvmgr_interrupt_unregister(uart->dev, 0, apbuart_cons_isr, tty);
459        }
460
461#ifdef LEON3
462        /* Disable TX/RX if not used for DEBUG */
463        if (uart->regs != leon3_debug_uart)
464                uart->regs->ctrl &= ~(APBUART_CTRL_RE | APBUART_CTRL_TE);
465#endif
466}
467
468static int read_polled(rtems_termios_device_context *base)
469{
470        struct apbuart_priv *uart = base_get_priv(base);
471
472        return apbuart_inbyte_nonblocking(uart->regs);
473}
474
475/* This function is called from TERMIOS rxdaemon task without device lock. */
476static int read_task(rtems_termios_device_context *base)
477{
478        rtems_interrupt_lock_context lock_context;
479        struct apbuart_priv *uart = base_get_priv(base);
480        struct apbuart_regs *regs = uart->regs;
481        int cnt;
482        char buf[33];
483        struct rtems_termios_tty *tty;
484        uint32_t ctrl_add;
485
486        ctrl_add = APBUART_CTRL_RI;
487        if (uart->cap & CAP_DI) {
488                ctrl_add |= (APBUART_CTRL_DI | APBUART_CTRL_RF);
489        }
490        tty = uart->tty;
491        do {
492                cnt = 0;
493                while (
494                        (regs->status & APBUART_STATUS_DR) &&
495                        (cnt < sizeof(buf))
496                ) {
497                        buf[cnt] = regs->data;
498                        cnt++;
499                }
500                if (0 < cnt) {
501                        /* Tell termios layer about new characters */
502                        rtems_termios_enqueue_raw_characters(tty, &buf[0], cnt);
503                }
504
505                /*
506                 * Turn on RX interrupts. A new character in FIFO now may not
507                 * cause interrupt so we must check data ready again
508                 * afterwards.
509                 */
510                rtems_termios_device_lock_acquire(base, &lock_context);
511                regs->ctrl |= ctrl_add;
512                rtems_termios_device_lock_release(base, &lock_context);
513        } while (regs->status & APBUART_STATUS_DR);
514
515        return EOF;
516}
517
518int apbuart_get_baud(struct apbuart_priv *uart)
519{
520        unsigned int core_clk_hz;
521        unsigned int scaler;
522
523        /* Get current scaler setting */
524        scaler = uart->regs->scaler;
525
526        /* Get APBUART core frequency */
527        drvmgr_freq_get(uart->dev, DEV_APB_SLV, &core_clk_hz);
528
529        /* Calculate baud rate from generator "scaler" number */
530        return core_clk_hz / ((scaler + 1) * 8);
531}
532
533static bool set_attributes(
534        rtems_termios_device_context *base,
535        const struct termios *t
536)
537{
538        unsigned int core_clk_hz;
539        unsigned int scaler;
540        unsigned int ctrl;
541        int baud;
542        struct apbuart_priv *uart = base_get_priv(base);
543        rtems_interrupt_lock_context lock_context;
544
545        switch(t->c_cflag & CSIZE) {
546                default:
547                case CS5:
548                case CS6:
549                case CS7:
550                        /* Hardware doesn't support other than CS8 */
551                        return false;
552                case CS8:
553                        break;
554        }
555
556        rtems_termios_device_lock_acquire(base, &lock_context);
557
558        /* Read out current value */
559        ctrl = uart->regs->ctrl;
560
561        switch(t->c_cflag & (PARENB|PARODD)){
562                case (PARENB|PARODD):
563                        /* Odd parity */
564                        ctrl |= APBUART_CTRL_PE|APBUART_CTRL_PS;
565                        break;
566
567                case PARENB:
568                        /* Even parity */
569                        ctrl &= ~APBUART_CTRL_PS;
570                        ctrl |= APBUART_CTRL_PE;
571                        break;
572
573                default:
574                case 0:
575                case PARODD:
576                        /* No Parity */
577                        ctrl &= ~(APBUART_CTRL_PS|APBUART_CTRL_PE);
578        }
579
580        if (!(t->c_cflag & CLOCAL))
581                ctrl |= APBUART_CTRL_FL;
582        else
583                ctrl &= ~APBUART_CTRL_FL;
584
585        /* Update new settings */
586        uart->regs->ctrl = ctrl;
587
588        rtems_termios_device_lock_release(base, &lock_context);
589
590        /* Baud rate */
591        baud = rtems_termios_baud_to_number(t->c_ospeed);
592        if (baud > 0){
593                /* Get APBUART core frequency */
594                drvmgr_freq_get(uart->dev, DEV_APB_SLV, &core_clk_hz);
595
596                /* Calculate Baud rate generator "scaler" number */
597                scaler = (((core_clk_hz*10)/(baud*8))-5)/10;
598
599                /* Set new baud rate by setting scaler */
600                uart->regs->scaler = scaler;
601        }
602
603        return true;
604}
605
606static void get_attributes(
607        rtems_termios_device_context *base,
608        struct termios *t
609)
610{
611        struct apbuart_priv *uart = base_get_priv(base);
612        unsigned int ctrl;
613
614        t->c_cflag = t->c_cflag & ~(CSIZE|PARENB|PARODD|CLOCAL);
615
616        /* Hardware support only CS8 */
617        t->c_cflag |= CS8;
618
619        /* Read out current parity */
620        ctrl = uart->regs->ctrl;
621        if (ctrl & APBUART_CTRL_PE) {
622                if (ctrl & APBUART_CTRL_PS)
623                        t->c_cflag |= PARENB|PARODD; /* Odd parity */
624                else
625                        t->c_cflag |= PARENB; /* Even parity */
626        }
627
628        if ((ctrl & APBUART_CTRL_FL) == 0)
629                t->c_cflag |= CLOCAL;
630
631        rtems_termios_set_best_baud(t, apbuart_get_baud(uart));
632}
633
634static void write_polled(
635        rtems_termios_device_context *base,
636        const char *buf,
637        size_t len
638)
639{
640        struct apbuart_priv *uart = base_get_priv(base);
641        int nwrite = 0;
642
643        while (nwrite < len) {
644                apbuart_outbyte_polled(uart->regs, *buf++, 0, 0);
645                nwrite++;
646        }
647}
648
649static void write_interrupt(
650        rtems_termios_device_context *base,
651        const char *buf,
652        size_t len
653)
654{
655        struct apbuart_priv *uart = base_get_priv(base);
656        struct apbuart_regs *regs = uart->regs;
657        int sending;
658        unsigned int ctrl;
659
660        ctrl = regs->ctrl;
661
662        if (len > 0) {
663                /*
664                 * sending is used to remember how much we have outstanding so
665                 * we can tell termios later.
666                 */
667                /* Enable TX interrupt (interrupt is edge-triggered) */
668                regs->ctrl = ctrl | APBUART_CTRL_TI;
669
670                if (ctrl & APBUART_CTRL_FA) {
671                        /* APBUART with FIFO.. Fill as many as FIFO allows */
672                        sending = 0;
673                        while (
674                                ((regs->status & APBUART_STATUS_TF) == 0) &&
675                                (sending < len)
676                        ) {
677                                regs->data = *buf;
678                                buf++;
679                                sending++;
680                        }
681                } else {
682                        /* start UART TX, this will result in an interrupt when done */
683                        regs->data = *buf;
684
685                        sending = 1;
686                }
687        } else {
688                /* No more to send, disable TX interrupts */
689                regs->ctrl = ctrl & ~APBUART_CTRL_TI;
690
691                /* Tell close that we sent everything */
692                sending = 0;
693        }
694
695        uart->sending = sending;
696}
697
698/* Handle UART interrupts */
699static void apbuart_cons_isr(void *arg)
700{
701        rtems_termios_tty *tty = arg;
702        rtems_termios_device_context *base;
703        struct console_dev *condev = rtems_termios_get_device_context(tty);
704        struct apbuart_priv *uart = condev_get_priv(condev);
705        struct apbuart_regs *regs = uart->regs;
706        unsigned int status;
707        char buf[33];
708        int cnt;
709
710        if (uart->mode == TERMIOS_TASK_DRIVEN) {
711                if ((status = regs->status) & APBUART_STATUS_DR) {
712                        rtems_interrupt_lock_context lock_context;
713
714                        /* Turn off RX interrupts */
715                        base = rtems_termios_get_device_context(tty);
716                        rtems_termios_device_lock_acquire(base, &lock_context);
717                        regs->ctrl &=
718                            ~(APBUART_CTRL_DI | APBUART_CTRL_RI |
719                              APBUART_CTRL_RF);
720                        rtems_termios_device_lock_release(base, &lock_context);
721                        /* Activate termios RX daemon task */
722                        rtems_termios_rxirq_occured(tty);
723                }
724        } else {
725                /*
726                 * Get all new characters from APBUART RX (FIFO) and store them
727                 * on the stack. Then tell termios about the new characters.
728                 * Maximum APBUART RX FIFO size is 32 characters.
729                 */
730                cnt = 0;
731                while (
732                        ((status=regs->status) & APBUART_STATUS_DR) &&
733                        (cnt < sizeof(buf))
734                ) {
735                        buf[cnt] = regs->data;
736                        cnt++;
737                }
738                if (0 < cnt) {
739                        /* Tell termios layer about new characters */
740                        rtems_termios_enqueue_raw_characters(tty, &buf[0], cnt);
741                }
742        }
743
744        if (uart->sending && (status & APBUART_STATUS_TE)) {
745                /* Tell close that we sent everything */
746                cnt = uart->sending;
747
748                /*
749                 * Tell termios how much we have sent. dequeue() may call
750                 * write_interrupt() to refill the transmitter.
751                 * write_interrupt() will eventually be called with 0 len to
752                 * disable TX interrupts.
753                 */
754                rtems_termios_dequeue_characters(tty, cnt);
755        }
756}
757
Note: See TracBrowser for help on using the repository browser.