Changeset d24ceb3 in rtems


Ignore:
Timestamp:
Nov 15, 1997, 6:15:36 PM (23 years ago)
Author:
Joel Sherrill <joel.sherrill@…>
Branches:
4.10, 4.11, 4.8, 4.9, 5, master
Children:
b5ddb74
Parents:
a307f79
Message:

interrupt driven change from Eric Norum

Files:
8 edited

Legend:

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

    ra307f79 rd24ceb3  
    140140  int                       (*deviceLastClose)(int major, int minor, void *arg),
    141141  int                       (*deviceRead)(int minor),
    142   int                       (*deviceWrite)(int minor, char *buf, int len)
     142  int                       (*deviceWrite)(int minor, char *buf, int len),
     143  int                         deviceOutputUsesInterrupts
    143144  );
    144145
  • c/src/exec/libcsupport/src/termios.c

    ra307f79 rd24ceb3  
    22 * TERMIOS serial line support
    33 *
    4  *  Authors:
     4 *  Author:
    55 *    W. Eric Norum
    66 *    Saskatchewan Accelerator Laboratory
     
    88 *    Saskatoon, Saskatchewan, CANADA
    99 *    eric@skatter.usask.ca
    10  *
    11  *    AND
    12  *
    13  *    Katsutoshi Shibuya
    14  *    BU Denken Co.,Ltd.
    15  *    Sapporo, JAPAN
    16  *    shibuya@mxb.meshnet.or.jp
    1710 *
    1811 *  The license and distribution terms for this file may be
     
    3831
    3932/*
    40  * The size of the raw input message queue
    41  */
    42 #define RAW_BUFFER_SIZE 128
     33 * The sizes of the raw message buffers.
     34 * On most architectures it is quite a bit more
     35 * efficient if these are powers of two.
     36 */
     37#define RAW_INPUT_BUFFER_SIZE   128
     38#define RAW_OUTPUT_BUFFER_SIZE  64
    4339
    4440/*
     
    9086
    9187        /*
    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 */
     88         * Raw input character buffer
     89         */
     90        volatile char           rawInBuf[RAW_INPUT_BUFFER_SIZE];
     91        volatile unsigned int   rawInBufHead;
     92        volatile unsigned int   rawInBufTail;
     93        rtems_id                rawInBufSemaphore;
     94        rtems_unsigned32        rawInBufSemaphoreOptions;
     95        rtems_interval          rawInBufSemaphoreTimeout;
     96        rtems_interval          rawInBufSemaphoreFirstTimeout;
     97        unsigned int            rawInBufDropped;        /* Statistics */
     98
     99        /*
     100         * Raw output character buffer
     101         */
     102        char                    outputUsesInterrupts;
     103        volatile char           rawOutBuf[RAW_OUTPUT_BUFFER_SIZE];
     104        volatile unsigned int   rawOutBufHead;
     105        volatile unsigned int   rawOutBufTail;
     106        rtems_id                rawOutBufSemaphore;
     107        enum {rob_idle, rob_busy, rob_wait }    rawOutBufState;
    102108
    103109        /*
     
    110116static struct rtems_termios_tty *ttyHead, *ttyTail;
    111117static rtems_id ttyMutex;
     118
     119/*
     120 *  Reserve enough resources to open every physical device once.
     121 */
     122void
     123rtems_termios_reserve_resources (
     124  rtems_configuration_table *configuration,
     125  rtems_unsigned32           number_of_devices
     126  )
     127{
     128        static int first_time = 1;
     129        rtems_api_configuration_table *rtems_config;
     130
     131        if (!configuration)
     132                rtems_fatal_error_occurred (0xFFF0F001);
     133        rtems_config = configuration->RTEMS_api_configuration;
     134        if (!rtems_config)
     135                rtems_fatal_error_occurred (0xFFF0F002);
     136        if (first_time)
     137                rtems_config->maximum_semaphores += 1;
     138        first_time = 0;
     139        rtems_config->maximum_semaphores += (4 * number_of_devices);
     140}
    112141
    113142void
     
    142171  int                      (*deviceLastClose)(int major, int minor, void *arg),
    143172  int                      (*deviceRead)(int minor),
    144   int                      (*deviceWrite)(int minor, char *buf, int len)
     173  int                      (*deviceWrite)(int minor, char *buf, int len),
     174  int                        deviceOutputUsesInterrupts
    145175  )
    146176{
     
    195225                if (sc != RTEMS_SUCCESSFUL)
    196226                        rtems_fatal_error_occurred (sc);
     227                sc = rtems_semaphore_create (
     228                        rtems_build_name ('T', 'R', 'x', c),
     229                        0,
     230                        RTEMS_COUNTING_SEMAPHORE | RTEMS_PRIORITY,
     231                        RTEMS_NO_PRIORITY,
     232                        &tty->rawOutBufSemaphore);
     233                if (sc != RTEMS_SUCCESSFUL)
     234                        rtems_fatal_error_occurred (sc);
     235                tty->rawOutBufHead = 0;
     236                tty->rawOutBufTail = 0;
    197237
    198238                /*
     
    207247                                RTEMS_COUNTING_SEMAPHORE | RTEMS_PRIORITY,
    208248                                RTEMS_NO_PRIORITY,
    209                                 &tty->rawBufSemaphore);
     249                                &tty->rawInBufSemaphore);
    210250                        if (sc != RTEMS_SUCCESSFUL)
    211251                                rtems_fatal_error_occurred (sc);
    212                         tty->rawBufHead = 0;
    213                         tty->rawBufTail = 0;
     252                        tty->rawInBufHead = 0;
     253                        tty->rawInBufTail = 0;
    214254                }
    215255
     
    219259                tty->column = 0;
    220260                tty->cindex = tty->ccount = 0;
     261                tty->outputUsesInterrupts = deviceOutputUsesInterrupts;
    221262
    222263                /*
     
    267308        rtems_status_code sc;
    268309
    269         args->ioctl_return = 0;
    270310        sc = rtems_semaphore_obtain (ttyMutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
    271311        if (sc != RTEMS_SUCCESSFUL)
     
    284324                rtems_semaphore_delete (tty->isem);
    285325                rtems_semaphore_delete (tty->osem);
     326                rtems_semaphore_delete (tty->rawOutBufSemaphore);
    286327                if (tty->read == NULL)
    287                         rtems_semaphore_delete (tty->rawBufSemaphore);
     328                        rtems_semaphore_delete (tty->rawInBufSemaphore);
    288329                free (tty);
    289330        }
     
    299340        rtems_status_code sc;
    300341
     342        args->ioctl_return = 0;
    301343        sc = rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
    302344        if (sc != RTEMS_SUCCESSFUL)
     
    314356                tty->termios = *(struct termios *)args->buffer;
    315357                if (tty->termios.c_lflag & ICANON) {
    316                         tty->rawBufSemaphoreOptions = RTEMS_WAIT;
    317                         tty->rawBufSemaphoreTimeout = RTEMS_NO_TIMEOUT;
    318                         tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
     358                        tty->rawInBufSemaphoreOptions = RTEMS_WAIT;
     359                        tty->rawInBufSemaphoreTimeout = RTEMS_NO_TIMEOUT;
     360                        tty->rawInBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
    319361                }
    320362                else {
     
    323365                        tty->vtimeTicks = tty->termios.c_cc[VTIME] * ticksPerSecond / 10;
    324366                        if (tty->termios.c_cc[VTIME]) {
    325                                 tty->rawBufSemaphoreOptions = RTEMS_WAIT;
    326                                 tty->rawBufSemap`oreTimeout = tty->vtimeTicks;
     367                                tty->rawInBufSemaphoreOptions = RTEMS_WAIT;
     368                                tty->rawInBufSemaphoreTimeout = tty->vtimeTicks;
    327369                                if (tty->termios.c_cc[VMIN])
    328                                         tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
     370                                        tty->rawInBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
    329371                                else
    330                                         tty->rawBufSemaphoreFirstTimeout = tty->vtimeTicks;
     372                                        tty->rawInBufSemaphoreFirstTimeout = tty->vtimeTicks;
    331373                        }
    332374                        else {
    333375                                if (tty->termios.c_cc[VMIN]) {
    334                                         tty->rawBufSemaphoreOptions = RTEMS_WAIT;
    335                                         tty->rawBufSemaphoreTimeout = RTEMS_NO_TIMEOUT;
    336                                         tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
     376                                        tty->rawInBufSemaphoreOptions = RTEMS_WAIT;
     377                                        tty->rawInBufSemaphoreTimeout = RTEMS_NO_TIMEOUT;
     378                                        tty->rawInBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
    337379                                }
    338380                                else {
    339                                         tty->rawBufSemaphoreOptions = RTEMS_NO_WAIT;
     381                                        tty->rawInBufSemaphoreOptions = RTEMS_NO_WAIT;
    340382                                }
    341383                        }
     
    345387        rtems_semaphore_release (tty->osem);
    346388        return sc;
     389}
     390
     391/*
     392 * Send characters to device-specific code
     393 */
     394static void
     395osend (const char *buf, int len, struct rtems_termios_tty *tty)
     396{
     397        unsigned int newHead;
     398        rtems_interrupt_level level;
     399        rtems_status_code sc;
     400
     401        if (!tty->outputUsesInterrupts) {
     402                (*tty->write)(tty->minor, buf, len);
     403                return;
     404        }
     405        newHead = tty->rawOutBufHead;
     406        while (len) {
     407                /*
     408                 * Performance improvement could be made here.
     409                 * Copy multiple bytes to raw buffer:
     410                 * if (len > 1) && (space to buffer end, or tail > 1)
     411                 *      ncopy = MIN (len, space to buffer end or tail)
     412                 *      memcpy (raw buffer, buf, ncopy)
     413                 *      buf += ncopy
     414                 *      len -= ncopy
     415                 *
     416                 * To minimize latency, the memcpy should be done
     417                 * with interrupts enabled.
     418                 */
     419                newHead = (newHead + 1) % RAW_OUTPUT_BUFFER_SIZE;
     420                rtems_interrupt_disable (level);
     421                while (newHead == tty->rawOutBufTail) {
     422                        tty->rawOutBufState = rob_wait;
     423                        rtems_interrupt_enable (level);
     424                        sc = rtems_semaphore_obtain (tty->rawOutBufSemaphore,
     425                                                        RTEMS_WAIT,
     426                                                        RTEMS_NO_TIMEOUT);
     427                        if (sc != RTEMS_SUCCESSFUL)
     428                                rtems_fatal_error_occurred (sc);
     429                        rtems_interrupt_disable (level);
     430                }
     431                tty->rawOutBuf[tty->rawOutBufHead] = *buf++;
     432                tty->rawOutBufHead = newHead;
     433                if (tty->rawOutBufState == rob_idle) {
     434                        rtems_interrupt_enable (level);
     435                        tty->rawOutBufState = rob_busy;
     436                        (*tty->write)(tty->minor, (char *)&tty->rawOutBuf[tty->rawOutBufTail], 1);
     437                }
     438                else {
     439                        rtems_interrupt_enable (level);
     440                }
     441                len--;
     442        }
    347443}
    348444
     
    361457                                tty->column = 0;
    362458                        if (tty->termios.c_oflag & ONLCR) {
    363                                 (*tty->write)(tty->minor, "\r", 1);
     459                                osend ("\r", 1, tty);
    364460                                tty->column = 0;
    365461                        }
     
    382478                        if ((tty->termios.c_oflag & TABDLY) == XTABS) {
    383479                                tty->column += i;
    384                                 (*tty->write)(tty->minor,  "        ",  i);
     480                                osend ( "        ",  i, tty);
    385481                                return;
    386482                        }
     
    401497                }
    402498        }
    403         (*tty->write)(tty->minor, &c, 1);
     499        osend (&c, 1, tty);
    404500}
    405501
     
    422518        }
    423519        else {
    424                 if ((*tty->write)(tty->minor, args->buffer, args->count) < 0)
    425                         sc = RTEMS_UNSATISFIED;
    426                 else
    427                         args->bytes_moved = args->count;
     520                osend (args->buffer, args->count, tty);
     521                args->bytes_moved = args->count;
    428522        }
    429523        rtems_semaphore_release (tty->osem);
     
    442536                echobuf[0] = '^';
    443537                echobuf[1] = c ^ 0x40;
    444                 (*tty->write)(tty->minor, echobuf, 2);
     538                osend (echobuf, 2, tty);
    445539                tty->column += 2;
    446540        }
     
    505599                                 */
    506600                                while (tty->column > col) {
    507                                         (*tty->write)(tty->minor, "\b", 1);
     601                                        osend ("\b", 1, tty);
    508602                                        tty->column--;
    509603                                }
     
    511605                        else {
    512606                                if (iscntrl (c) && (tty->termios.c_lflag & ECHOCTL)) {
    513                                         (*tty->write)(tty->minor, "\b \b", 3);
     607                                        osend ("\b \b", 3, tty);
    514608                                        if (tty->column)
    515609                                                tty->column--;
    516610                                }
    517611                                if (!iscntrl (c) || (tty->termios.c_lflag & ECHOCTL)) {
    518                                         (*tty->write)(tty->minor, "\b \b", 3);
     612                                        osend ("\b \b", 3, tty);
    519613                                        if (tty->column)
    520614                                                tty->column--;
     
    669763fillBufferQueue (struct rtems_termios_tty *tty)
    670764{
    671         rtems_interval timeout = tty->rawBufSemaphoreFirstTimeout;
     765        rtems_interval timeout = tty->rawInBufSemaphoreFirstTimeout;
    672766        rtems_status_code sc;
    673767
     
    676770                 * Process characters read from raw queue
    677771                 */
    678                 while (tty->rawBufHead != tty->rawBufTail) {
     772                while (tty->rawInBufHead != tty->rawInBufTail) {
    679773                        unsigned char c;
    680774                        unsigned int newHead;
    681775
    682                         newHead = (tty->rawBufHead + 1) % RAW_BUFFER_SIZE;
    683                         c = tty->rawBuf[newHead];
    684                         tty->rawBufHead = newHead;
     776                        newHead = (tty->rawInBufHead + 1) % RAW_INPUT_BUFFER_SIZE;
     777                        c = tty->rawInBuf[newHead];
     778                        tty->rawInBufHead = newHead;
    685779                        if (tty->termios.c_lflag & ICANON) {
    686780                                if  (siproc (c, tty))
     
    692786                                        return RTEMS_SUCCESSFUL;
    693787                        }
    694                         timeout = tty->rawBufSemaphoreTimeout;
     788                        timeout = tty->rawInBufSemaphoreTimeout;
    695789                }
    696790
     
    698792                 * Wait for characters
    699793                 */
    700                 sc = rtems_semaphore_obtain (tty->rawBufSemaphore,
    701                                                 tty->rawBufSemaphoreOptions,
     794                sc = rtems_semaphore_obtain (tty->rawInBufSemaphore,
     795                                                tty->rawInBufSemaphoreOptions,
    702796                                                timeout);
    703797                if (sc != RTEMS_SUCCESSFUL)
     
    740834/*
    741835 * Place characters on raw queue.
    742  * NOTE: This routine runs in the context of the device interrupt handler.
     836 * NOTE: This routine runs in the context of the
     837 *       device receive interrupt handler.
    743838 */
    744839void
     
    749844
    750845        while (len) {
    751                 newTail = (tty->rawBufTail + 1) % RAW_BUFFER_SIZE;
    752                 if (newTail == tty->rawBufHead) {
    753                         tty->rawBufDropped += len;
     846                newTail = (tty->rawInBufTail + 1) % RAW_INPUT_BUFFER_SIZE;
     847                if (newTail == tty->rawInBufHead) {
     848                        tty->rawInBufDropped += len;
    754849                        break;
    755850                }
    756                 tty->rawBuf[newTail] = *buf++;
     851                tty->rawInBuf[newTail] = *buf++;
    757852                len--;
    758                 tty->rawBufTail = newTail;
    759         }
    760         rtems_semaphore_release (tty->rawBufSemaphore);
    761 }
    762 
    763 /*
    764  *  Reserve enough resources to open every physical device once.
    765  */
    766 
    767 void 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 }
     853                tty->rawInBufTail = newTail;
     854        }
     855        rtems_semaphore_release (tty->rawInBufSemaphore);
     856}
     857
     858/*
     859 * Characters have been transmitted
     860 * NOTE: This routine runs in the context of the
     861 *       device transmit interrupt handler.
     862 * The second argument is the number of characters transmitted so far.
     863 * This value will always be 1 for devices which generate an interrupt
     864 * for each transmitted character.
     865 */
     866void
     867rtems_termios_dequeue_characters (void *ttyp, int len)
     868{
     869        struct rtems_termios_tty *tty = ttyp;
     870        unsigned int newTail;
     871        int nToSend;
     872
     873        if (tty->rawOutBufState == rob_wait)
     874                rtems_semaphore_release (tty->rawOutBufSemaphore);
     875        newTail = (tty->rawOutBufTail + len) % RAW_OUTPUT_BUFFER_SIZE;
     876        if (newTail == tty->rawOutBufHead) {
     877                /*
     878                 * Buffer empty
     879                 */
     880                tty->rawOutBufState = rob_idle;
     881        }
     882        else {
     883                /*
     884                 * Buffer not empty, start tranmitter
     885                 */
     886                tty->rawOutBufState = rob_busy;
     887                if (newTail > tty->rawOutBufHead)
     888                        nToSend = RAW_OUTPUT_BUFFER_SIZE - newTail;
     889                else
     890                        nToSend = tty->rawOutBufHead - newTail;
     891                (*tty->write)(tty->minor, (char *)&tty->rawOutBuf[newTail], nToSend);
     892        }
     893        tty->rawOutBufTail = newTail;
     894}
  • c/src/lib/include/rtems/libio.h

    ra307f79 rd24ceb3  
    140140  int                       (*deviceLastClose)(int major, int minor, void *arg),
    141141  int                       (*deviceRead)(int minor),
    142   int                       (*deviceWrite)(int minor, char *buf, int len)
     142  int                       (*deviceWrite)(int minor, char *buf, int len),
     143  int                         deviceOutputUsesInterrupts
    143144  );
    144145
  • c/src/lib/libbsp/m68k/gen68360/console/console.c

    ra307f79 rd24ceb3  
    4141 * I/O buffers and pointers to buffer descriptors
    4242 */
    43 static volatile char rxBuf[RXBUFSIZE], txBuf;
     43static volatile char rxBuf[RXBUFSIZE];
    4444static volatile m360BufferDescriptor_t *smcRxBd, *smcTxBd;
    4545
     
    6363                }
    6464        }
     65
     66        /*
     67         * Buffer transmitted?
     68         */
     69        if (m360.smc1.smce & 0x2) {
     70                m360.smc1.smce = 0x2;
     71                if ((smcTxBd->status & M360_BD_READY) == 0)
     72                        rtems_termios_dequeue_characters (smc1ttyp, smcTxBd->length);
     73        }
    6574        m360.cisr = 1UL << 4;   /* Clear SMC1 interrupt-in-service bit */
    6675}
     
    123132         */
    124133        smcTxBd->status = M360_BD_WRAP;
    125         smcTxBd->length = 1;
    126         smcTxBd->buffer = &txBuf;
    127134         
    128135        /*
     
    151158                                                (m360.cicr & 0xE0) | 0x04,
    152159                                                &old_handler);
    153         m360.smc1.smcm = 1;     /* Enable SMC1 receiver interrupt */
     160        m360.smc1.smcm = 3;     /* Enable SMC1 TX and RX interrupts */
    154161        m360.cimr |= 1UL << 4;  /* Enable SMC1 interrupts */
    155162        }
     
    169176}
    170177
     178/*
     179 * Device-dependent write routine
     180 * Interrupt-driven devices:
     181 *      Begin transmission of as many characters as possible (minimum is 1).
     182 * Polling devices:
     183 *      Transmit all characters.
     184 */
    171185static int
    172186smc1Write (int minor, char *buf, int len)
    173187{
    174         int nwrite = 0;
    175 
    176         while (nwrite < len) {
     188#if (defined (M360_SMC1_INTERRUPT))
     189        smcTxBd->buffer = buf;
     190        smcTxBd->length = len;
     191        smcTxBd->status = M360_BD_READY | M360_BD_WRAP | M360_BD_INTERRUPT;
     192#else
     193        while (len--) {
     194                static char txBuf;
    177195                while (smcTxBd->status & M360_BD_READY)
    178196                        continue;
    179197                txBuf = *buf++;
     198                smcTxBd->buffer = &txBuf;
     199                smcTxBd->length = 1;
    180200                smcTxBd->status = M360_BD_READY | M360_BD_WRAP;
    181                 nwrite++;
    182201        }
    183         return nwrite;
     202#endif
     203        return 0;
    184204}
    185205
     
    189209 ***************
    190210 */
     211
     212/*
     213 * Reserve resources consumed by this driver
     214 */
     215void console_reserve_resources(
     216  rtems_configuration_table *configuration
     217)
     218{
     219        rtems_termios_reserve_resources (configuration, 1);
     220}
    191221
    192222/*
     
    238268                        NULL,
    239269                        NULL,
    240                         smc1Write);
     270                        smc1Write,
     271                        1);
    241272        smc1ttyp = args->iop->data1;
    242273#else
     
    245276                        NULL,
    246277                        smc1Read,
    247                         smc1Write);
     278                        smc1Write,
     279                        0);
    248280#endif
    249281        return sc;
  • c/src/lib/libc/libio.h

    ra307f79 rd24ceb3  
    140140  int                       (*deviceLastClose)(int major, int minor, void *arg),
    141141  int                       (*deviceRead)(int minor),
    142   int                       (*deviceWrite)(int minor, char *buf, int len)
     142  int                       (*deviceWrite)(int minor, char *buf, int len),
     143  int                         deviceOutputUsesInterrupts
    143144  );
    144145
  • c/src/lib/libc/termios.c

    ra307f79 rd24ceb3  
    22 * TERMIOS serial line support
    33 *
    4  *  Authors:
     4 *  Author:
    55 *    W. Eric Norum
    66 *    Saskatchewan Accelerator Laboratory
     
    88 *    Saskatoon, Saskatchewan, CANADA
    99 *    eric@skatter.usask.ca
    10  *
    11  *    AND
    12  *
    13  *    Katsutoshi Shibuya
    14  *    BU Denken Co.,Ltd.
    15  *    Sapporo, JAPAN
    16  *    shibuya@mxb.meshnet.or.jp
    1710 *
    1811 *  The license and distribution terms for this file may be
     
    3831
    3932/*
    40  * The size of the raw input message queue
    41  */
    42 #define RAW_BUFFER_SIZE 128
     33 * The sizes of the raw message buffers.
     34 * On most architectures it is quite a bit more
     35 * efficient if these are powers of two.
     36 */
     37#define RAW_INPUT_BUFFER_SIZE   128
     38#define RAW_OUTPUT_BUFFER_SIZE  64
    4339
    4440/*
     
    9086
    9187        /*
    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 */
     88         * Raw input character buffer
     89         */
     90        volatile char           rawInBuf[RAW_INPUT_BUFFER_SIZE];
     91        volatile unsigned int   rawInBufHead;
     92        volatile unsigned int   rawInBufTail;
     93        rtems_id                rawInBufSemaphore;
     94        rtems_unsigned32        rawInBufSemaphoreOptions;
     95        rtems_interval          rawInBufSemaphoreTimeout;
     96        rtems_interval          rawInBufSemaphoreFirstTimeout;
     97        unsigned int            rawInBufDropped;        /* Statistics */
     98
     99        /*
     100         * Raw output character buffer
     101         */
     102        char                    outputUsesInterrupts;
     103        volatile char           rawOutBuf[RAW_OUTPUT_BUFFER_SIZE];
     104        volatile unsigned int   rawOutBufHead;
     105        volatile unsigned int   rawOutBufTail;
     106        rtems_id                rawOutBufSemaphore;
     107        enum {rob_idle, rob_busy, rob_wait }    rawOutBufState;
    102108
    103109        /*
     
    110116static struct rtems_termios_tty *ttyHead, *ttyTail;
    111117static rtems_id ttyMutex;
     118
     119/*
     120 *  Reserve enough resources to open every physical device once.
     121 */
     122void
     123rtems_termios_reserve_resources (
     124  rtems_configuration_table *configuration,
     125  rtems_unsigned32           number_of_devices
     126  )
     127{
     128        static int first_time = 1;
     129        rtems_api_configuration_table *rtems_config;
     130
     131        if (!configuration)
     132                rtems_fatal_error_occurred (0xFFF0F001);
     133        rtems_config = configuration->RTEMS_api_configuration;
     134        if (!rtems_config)
     135                rtems_fatal_error_occurred (0xFFF0F002);
     136        if (first_time)
     137                rtems_config->maximum_semaphores += 1;
     138        first_time = 0;
     139        rtems_config->maximum_semaphores += (4 * number_of_devices);
     140}
    112141
    113142void
     
    142171  int                      (*deviceLastClose)(int major, int minor, void *arg),
    143172  int                      (*deviceRead)(int minor),
    144   int                      (*deviceWrite)(int minor, char *buf, int len)
     173  int                      (*deviceWrite)(int minor, char *buf, int len),
     174  int                        deviceOutputUsesInterrupts
    145175  )
    146176{
     
    195225                if (sc != RTEMS_SUCCESSFUL)
    196226                        rtems_fatal_error_occurred (sc);
     227                sc = rtems_semaphore_create (
     228                        rtems_build_name ('T', 'R', 'x', c),
     229                        0,
     230                        RTEMS_COUNTING_SEMAPHORE | RTEMS_PRIORITY,
     231                        RTEMS_NO_PRIORITY,
     232                        &tty->rawOutBufSemaphore);
     233                if (sc != RTEMS_SUCCESSFUL)
     234                        rtems_fatal_error_occurred (sc);
     235                tty->rawOutBufHead = 0;
     236                tty->rawOutBufTail = 0;
    197237
    198238                /*
     
    207247                                RTEMS_COUNTING_SEMAPHORE | RTEMS_PRIORITY,
    208248                                RTEMS_NO_PRIORITY,
    209                                 &tty->rawBufSemaphore);
     249                                &tty->rawInBufSemaphore);
    210250                        if (sc != RTEMS_SUCCESSFUL)
    211251                                rtems_fatal_error_occurred (sc);
    212                         tty->rawBufHead = 0;
    213                         tty->rawBufTail = 0;
     252                        tty->rawInBufHead = 0;
     253                        tty->rawInBufTail = 0;
    214254                }
    215255
     
    219259                tty->column = 0;
    220260                tty->cindex = tty->ccount = 0;
     261                tty->outputUsesInterrupts = deviceOutputUsesInterrupts;
    221262
    222263                /*
     
    267308        rtems_status_code sc;
    268309
    269         args->ioctl_return = 0;
    270310        sc = rtems_semaphore_obtain (ttyMutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
    271311        if (sc != RTEMS_SUCCESSFUL)
     
    284324                rtems_semaphore_delete (tty->isem);
    285325                rtems_semaphore_delete (tty->osem);
     326                rtems_semaphore_delete (tty->rawOutBufSemaphore);
    286327                if (tty->read == NULL)
    287                         rtems_semaphore_delete (tty->rawBufSemaphore);
     328                        rtems_semaphore_delete (tty->rawInBufSemaphore);
    288329                free (tty);
    289330        }
     
    299340        rtems_status_code sc;
    300341
     342        args->ioctl_return = 0;
    301343        sc = rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
    302344        if (sc != RTEMS_SUCCESSFUL)
     
    314356                tty->termios = *(struct termios *)args->buffer;
    315357                if (tty->termios.c_lflag & ICANON) {
    316                         tty->rawBufSemaphoreOptions = RTEMS_WAIT;
    317                         tty->rawBufSemaphoreTimeout = RTEMS_NO_TIMEOUT;
    318                         tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
     358                        tty->rawInBufSemaphoreOptions = RTEMS_WAIT;
     359                        tty->rawInBufSemaphoreTimeout = RTEMS_NO_TIMEOUT;
     360                        tty->rawInBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
    319361                }
    320362                else {
     
    323365                        tty->vtimeTicks = tty->termios.c_cc[VTIME] * ticksPerSecond / 10;
    324366                        if (tty->termios.c_cc[VTIME]) {
    325                                 tty->rawBufSemaphoreOptions = RTEMS_WAIT;
    326                                 tty->rawBufSemap`oreTimeout = tty->vtimeTicks;
     367                                tty->rawInBufSemaphoreOptions = RTEMS_WAIT;
     368                                tty->rawInBufSemaphoreTimeout = tty->vtimeTicks;
    327369                                if (tty->termios.c_cc[VMIN])
    328                                         tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
     370                                        tty->rawInBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
    329371                                else
    330                                         tty->rawBufSemaphoreFirstTimeout = tty->vtimeTicks;
     372                                        tty->rawInBufSemaphoreFirstTimeout = tty->vtimeTicks;
    331373                        }
    332374                        else {
    333375                                if (tty->termios.c_cc[VMIN]) {
    334                                         tty->rawBufSemaphoreOptions = RTEMS_WAIT;
    335                                         tty->rawBufSemaphoreTimeout = RTEMS_NO_TIMEOUT;
    336                                         tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
     376                                        tty->rawInBufSemaphoreOptions = RTEMS_WAIT;
     377                                        tty->rawInBufSemaphoreTimeout = RTEMS_NO_TIMEOUT;
     378                                        tty->rawInBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
    337379                                }
    338380                                else {
    339                                         tty->rawBufSemaphoreOptions = RTEMS_NO_WAIT;
     381                                        tty->rawInBufSemaphoreOptions = RTEMS_NO_WAIT;
    340382                                }
    341383                        }
     
    345387        rtems_semaphore_release (tty->osem);
    346388        return sc;
     389}
     390
     391/*
     392 * Send characters to device-specific code
     393 */
     394static void
     395osend (const char *buf, int len, struct rtems_termios_tty *tty)
     396{
     397        unsigned int newHead;
     398        rtems_interrupt_level level;
     399        rtems_status_code sc;
     400
     401        if (!tty->outputUsesInterrupts) {
     402                (*tty->write)(tty->minor, buf, len);
     403                return;
     404        }
     405        newHead = tty->rawOutBufHead;
     406        while (len) {
     407                /*
     408                 * Performance improvement could be made here.
     409                 * Copy multiple bytes to raw buffer:
     410                 * if (len > 1) && (space to buffer end, or tail > 1)
     411                 *      ncopy = MIN (len, space to buffer end or tail)
     412                 *      memcpy (raw buffer, buf, ncopy)
     413                 *      buf += ncopy
     414                 *      len -= ncopy
     415                 *
     416                 * To minimize latency, the memcpy should be done
     417                 * with interrupts enabled.
     418                 */
     419                newHead = (newHead + 1) % RAW_OUTPUT_BUFFER_SIZE;
     420                rtems_interrupt_disable (level);
     421                while (newHead == tty->rawOutBufTail) {
     422                        tty->rawOutBufState = rob_wait;
     423                        rtems_interrupt_enable (level);
     424                        sc = rtems_semaphore_obtain (tty->rawOutBufSemaphore,
     425                                                        RTEMS_WAIT,
     426                                                        RTEMS_NO_TIMEOUT);
     427                        if (sc != RTEMS_SUCCESSFUL)
     428                                rtems_fatal_error_occurred (sc);
     429                        rtems_interrupt_disable (level);
     430                }
     431                tty->rawOutBuf[tty->rawOutBufHead] = *buf++;
     432                tty->rawOutBufHead = newHead;
     433                if (tty->rawOutBufState == rob_idle) {
     434                        rtems_interrupt_enable (level);
     435                        tty->rawOutBufState = rob_busy;
     436                        (*tty->write)(tty->minor, (char *)&tty->rawOutBuf[tty->rawOutBufTail], 1);
     437                }
     438                else {
     439                        rtems_interrupt_enable (level);
     440                }
     441                len--;
     442        }
    347443}
    348444
     
    361457                                tty->column = 0;
    362458                        if (tty->termios.c_oflag & ONLCR) {
    363                                 (*tty->write)(tty->minor, "\r", 1);
     459                                osend ("\r", 1, tty);
    364460                                tty->column = 0;
    365461                        }
     
    382478                        if ((tty->termios.c_oflag & TABDLY) == XTABS) {
    383479                                tty->column += i;
    384                                 (*tty->write)(tty->minor,  "        ",  i);
     480                                osend ( "        ",  i, tty);
    385481                                return;
    386482                        }
     
    401497                }
    402498        }
    403         (*tty->write)(tty->minor, &c, 1);
     499        osend (&c, 1, tty);
    404500}
    405501
     
    422518        }
    423519        else {
    424                 if ((*tty->write)(tty->minor, args->buffer, args->count) < 0)
    425                         sc = RTEMS_UNSATISFIED;
    426                 else
    427                         args->bytes_moved = args->count;
     520                osend (args->buffer, args->count, tty);
     521                args->bytes_moved = args->count;
    428522        }
    429523        rtems_semaphore_release (tty->osem);
     
    442536                echobuf[0] = '^';
    443537                echobuf[1] = c ^ 0x40;
    444                 (*tty->write)(tty->minor, echobuf, 2);
     538                osend (echobuf, 2, tty);
    445539                tty->column += 2;
    446540        }
     
    505599                                 */
    506600                                while (tty->column > col) {
    507                                         (*tty->write)(tty->minor, "\b", 1);
     601                                        osend ("\b", 1, tty);
    508602                                        tty->column--;
    509603                                }
     
    511605                        else {
    512606                                if (iscntrl (c) && (tty->termios.c_lflag & ECHOCTL)) {
    513                                         (*tty->write)(tty->minor, "\b \b", 3);
     607                                        osend ("\b \b", 3, tty);
    514608                                        if (tty->column)
    515609                                                tty->column--;
    516610                                }
    517611                                if (!iscntrl (c) || (tty->termios.c_lflag & ECHOCTL)) {
    518                                         (*tty->write)(tty->minor, "\b \b", 3);
     612                                        osend ("\b \b", 3, tty);
    519613                                        if (tty->column)
    520614                                                tty->column--;
     
    669763fillBufferQueue (struct rtems_termios_tty *tty)
    670764{
    671         rtems_interval timeout = tty->rawBufSemaphoreFirstTimeout;
     765        rtems_interval timeout = tty->rawInBufSemaphoreFirstTimeout;
    672766        rtems_status_code sc;
    673767
     
    676770                 * Process characters read from raw queue
    677771                 */
    678                 while (tty->rawBufHead != tty->rawBufTail) {
     772                while (tty->rawInBufHead != tty->rawInBufTail) {
    679773                        unsigned char c;
    680774                        unsigned int newHead;
    681775
    682                         newHead = (tty->rawBufHead + 1) % RAW_BUFFER_SIZE;
    683                         c = tty->rawBuf[newHead];
    684                         tty->rawBufHead = newHead;
     776                        newHead = (tty->rawInBufHead + 1) % RAW_INPUT_BUFFER_SIZE;
     777                        c = tty->rawInBuf[newHead];
     778                        tty->rawInBufHead = newHead;
    685779                        if (tty->termios.c_lflag & ICANON) {
    686780                                if  (siproc (c, tty))
     
    692786                                        return RTEMS_SUCCESSFUL;
    693787                        }
    694                         timeout = tty->rawBufSemaphoreTimeout;
     788                        timeout = tty->rawInBufSemaphoreTimeout;
    695789                }
    696790
     
    698792                 * Wait for characters
    699793                 */
    700                 sc = rtems_semaphore_obtain (tty->rawBufSemaphore,
    701                                                 tty->rawBufSemaphoreOptions,
     794                sc = rtems_semaphore_obtain (tty->rawInBufSemaphore,
     795                                                tty->rawInBufSemaphoreOptions,
    702796                                                timeout);
    703797                if (sc != RTEMS_SUCCESSFUL)
     
    740834/*
    741835 * Place characters on raw queue.
    742  * NOTE: This routine runs in the context of the device interrupt handler.
     836 * NOTE: This routine runs in the context of the
     837 *       device receive interrupt handler.
    743838 */
    744839void
     
    749844
    750845        while (len) {
    751                 newTail = (tty->rawBufTail + 1) % RAW_BUFFER_SIZE;
    752                 if (newTail == tty->rawBufHead) {
    753                         tty->rawBufDropped += len;
     846                newTail = (tty->rawInBufTail + 1) % RAW_INPUT_BUFFER_SIZE;
     847                if (newTail == tty->rawInBufHead) {
     848                        tty->rawInBufDropped += len;
    754849                        break;
    755850                }
    756                 tty->rawBuf[newTail] = *buf++;
     851                tty->rawInBuf[newTail] = *buf++;
    757852                len--;
    758                 tty->rawBufTail = newTail;
    759         }
    760         rtems_semaphore_release (tty->rawBufSemaphore);
    761 }
    762 
    763 /*
    764  *  Reserve enough resources to open every physical device once.
    765  */
    766 
    767 void 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 }
     853                tty->rawInBufTail = newTail;
     854        }
     855        rtems_semaphore_release (tty->rawInBufSemaphore);
     856}
     857
     858/*
     859 * Characters have been transmitted
     860 * NOTE: This routine runs in the context of the
     861 *       device transmit interrupt handler.
     862 * The second argument is the number of characters transmitted so far.
     863 * This value will always be 1 for devices which generate an interrupt
     864 * for each transmitted character.
     865 */
     866void
     867rtems_termios_dequeue_characters (void *ttyp, int len)
     868{
     869        struct rtems_termios_tty *tty = ttyp;
     870        unsigned int newTail;
     871        int nToSend;
     872
     873        if (tty->rawOutBufState == rob_wait)
     874                rtems_semaphore_release (tty->rawOutBufSemaphore);
     875        newTail = (tty->rawOutBufTail + len) % RAW_OUTPUT_BUFFER_SIZE;
     876        if (newTail == tty->rawOutBufHead) {
     877                /*
     878                 * Buffer empty
     879                 */
     880                tty->rawOutBufState = rob_idle;
     881        }
     882        else {
     883                /*
     884                 * Buffer not empty, start tranmitter
     885                 */
     886                tty->rawOutBufState = rob_busy;
     887                if (newTail > tty->rawOutBufHead)
     888                        nToSend = RAW_OUTPUT_BUFFER_SIZE - newTail;
     889                else
     890                        nToSend = tty->rawOutBufHead - newTail;
     891                (*tty->write)(tty->minor, (char *)&tty->rawOutBuf[newTail], nToSend);
     892        }
     893        tty->rawOutBufTail = newTail;
     894}
  • cpukit/libcsupport/include/rtems/libio.h

    ra307f79 rd24ceb3  
    140140  int                       (*deviceLastClose)(int major, int minor, void *arg),
    141141  int                       (*deviceRead)(int minor),
    142   int                       (*deviceWrite)(int minor, char *buf, int len)
     142  int                       (*deviceWrite)(int minor, char *buf, int len),
     143  int                         deviceOutputUsesInterrupts
    143144  );
    144145
  • cpukit/libcsupport/src/termios.c

    ra307f79 rd24ceb3  
    22 * TERMIOS serial line support
    33 *
    4  *  Authors:
     4 *  Author:
    55 *    W. Eric Norum
    66 *    Saskatchewan Accelerator Laboratory
     
    88 *    Saskatoon, Saskatchewan, CANADA
    99 *    eric@skatter.usask.ca
    10  *
    11  *    AND
    12  *
    13  *    Katsutoshi Shibuya
    14  *    BU Denken Co.,Ltd.
    15  *    Sapporo, JAPAN
    16  *    shibuya@mxb.meshnet.or.jp
    1710 *
    1811 *  The license and distribution terms for this file may be
     
    3831
    3932/*
    40  * The size of the raw input message queue
    41  */
    42 #define RAW_BUFFER_SIZE 128
     33 * The sizes of the raw message buffers.
     34 * On most architectures it is quite a bit more
     35 * efficient if these are powers of two.
     36 */
     37#define RAW_INPUT_BUFFER_SIZE   128
     38#define RAW_OUTPUT_BUFFER_SIZE  64
    4339
    4440/*
     
    9086
    9187        /*
    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 */
     88         * Raw input character buffer
     89         */
     90        volatile char           rawInBuf[RAW_INPUT_BUFFER_SIZE];
     91        volatile unsigned int   rawInBufHead;
     92        volatile unsigned int   rawInBufTail;
     93        rtems_id                rawInBufSemaphore;
     94        rtems_unsigned32        rawInBufSemaphoreOptions;
     95        rtems_interval          rawInBufSemaphoreTimeout;
     96        rtems_interval          rawInBufSemaphoreFirstTimeout;
     97        unsigned int            rawInBufDropped;        /* Statistics */
     98
     99        /*
     100         * Raw output character buffer
     101         */
     102        char                    outputUsesInterrupts;
     103        volatile char           rawOutBuf[RAW_OUTPUT_BUFFER_SIZE];
     104        volatile unsigned int   rawOutBufHead;
     105        volatile unsigned int   rawOutBufTail;
     106        rtems_id                rawOutBufSemaphore;
     107        enum {rob_idle, rob_busy, rob_wait }    rawOutBufState;
    102108
    103109        /*
     
    110116static struct rtems_termios_tty *ttyHead, *ttyTail;
    111117static rtems_id ttyMutex;
     118
     119/*
     120 *  Reserve enough resources to open every physical device once.
     121 */
     122void
     123rtems_termios_reserve_resources (
     124  rtems_configuration_table *configuration,
     125  rtems_unsigned32           number_of_devices
     126  )
     127{
     128        static int first_time = 1;
     129        rtems_api_configuration_table *rtems_config;
     130
     131        if (!configuration)
     132                rtems_fatal_error_occurred (0xFFF0F001);
     133        rtems_config = configuration->RTEMS_api_configuration;
     134        if (!rtems_config)
     135                rtems_fatal_error_occurred (0xFFF0F002);
     136        if (first_time)
     137                rtems_config->maximum_semaphores += 1;
     138        first_time = 0;
     139        rtems_config->maximum_semaphores += (4 * number_of_devices);
     140}
    112141
    113142void
     
    142171  int                      (*deviceLastClose)(int major, int minor, void *arg),
    143172  int                      (*deviceRead)(int minor),
    144   int                      (*deviceWrite)(int minor, char *buf, int len)
     173  int                      (*deviceWrite)(int minor, char *buf, int len),
     174  int                        deviceOutputUsesInterrupts
    145175  )
    146176{
     
    195225                if (sc != RTEMS_SUCCESSFUL)
    196226                        rtems_fatal_error_occurred (sc);
     227                sc = rtems_semaphore_create (
     228                        rtems_build_name ('T', 'R', 'x', c),
     229                        0,
     230                        RTEMS_COUNTING_SEMAPHORE | RTEMS_PRIORITY,
     231                        RTEMS_NO_PRIORITY,
     232                        &tty->rawOutBufSemaphore);
     233                if (sc != RTEMS_SUCCESSFUL)
     234                        rtems_fatal_error_occurred (sc);
     235                tty->rawOutBufHead = 0;
     236                tty->rawOutBufTail = 0;
    197237
    198238                /*
     
    207247                                RTEMS_COUNTING_SEMAPHORE | RTEMS_PRIORITY,
    208248                                RTEMS_NO_PRIORITY,
    209                                 &tty->rawBufSemaphore);
     249                                &tty->rawInBufSemaphore);
    210250                        if (sc != RTEMS_SUCCESSFUL)
    211251                                rtems_fatal_error_occurred (sc);
    212                         tty->rawBufHead = 0;
    213                         tty->rawBufTail = 0;
     252                        tty->rawInBufHead = 0;
     253                        tty->rawInBufTail = 0;
    214254                }
    215255
     
    219259                tty->column = 0;
    220260                tty->cindex = tty->ccount = 0;
     261                tty->outputUsesInterrupts = deviceOutputUsesInterrupts;
    221262
    222263                /*
     
    267308        rtems_status_code sc;
    268309
    269         args->ioctl_return = 0;
    270310        sc = rtems_semaphore_obtain (ttyMutex, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
    271311        if (sc != RTEMS_SUCCESSFUL)
     
    284324                rtems_semaphore_delete (tty->isem);
    285325                rtems_semaphore_delete (tty->osem);
     326                rtems_semaphore_delete (tty->rawOutBufSemaphore);
    286327                if (tty->read == NULL)
    287                         rtems_semaphore_delete (tty->rawBufSemaphore);
     328                        rtems_semaphore_delete (tty->rawInBufSemaphore);
    288329                free (tty);
    289330        }
     
    299340        rtems_status_code sc;
    300341
     342        args->ioctl_return = 0;
    301343        sc = rtems_semaphore_obtain (tty->osem, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
    302344        if (sc != RTEMS_SUCCESSFUL)
     
    314356                tty->termios = *(struct termios *)args->buffer;
    315357                if (tty->termios.c_lflag & ICANON) {
    316                         tty->rawBufSemaphoreOptions = RTEMS_WAIT;
    317                         tty->rawBufSemaphoreTimeout = RTEMS_NO_TIMEOUT;
    318                         tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
     358                        tty->rawInBufSemaphoreOptions = RTEMS_WAIT;
     359                        tty->rawInBufSemaphoreTimeout = RTEMS_NO_TIMEOUT;
     360                        tty->rawInBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
    319361                }
    320362                else {
     
    323365                        tty->vtimeTicks = tty->termios.c_cc[VTIME] * ticksPerSecond / 10;
    324366                        if (tty->termios.c_cc[VTIME]) {
    325                                 tty->rawBufSemaphoreOptions = RTEMS_WAIT;
    326                                 tty->rawBufSemap`oreTimeout = tty->vtimeTicks;
     367                                tty->rawInBufSemaphoreOptions = RTEMS_WAIT;
     368                                tty->rawInBufSemaphoreTimeout = tty->vtimeTicks;
    327369                                if (tty->termios.c_cc[VMIN])
    328                                         tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
     370                                        tty->rawInBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
    329371                                else
    330                                         tty->rawBufSemaphoreFirstTimeout = tty->vtimeTicks;
     372                                        tty->rawInBufSemaphoreFirstTimeout = tty->vtimeTicks;
    331373                        }
    332374                        else {
    333375                                if (tty->termios.c_cc[VMIN]) {
    334                                         tty->rawBufSemaphoreOptions = RTEMS_WAIT;
    335                                         tty->rawBufSemaphoreTimeout = RTEMS_NO_TIMEOUT;
    336                                         tty->rawBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
     376                                        tty->rawInBufSemaphoreOptions = RTEMS_WAIT;
     377                                        tty->rawInBufSemaphoreTimeout = RTEMS_NO_TIMEOUT;
     378                                        tty->rawInBufSemaphoreFirstTimeout = RTEMS_NO_TIMEOUT;
    337379                                }
    338380                                else {
    339                                         tty->rawBufSemaphoreOptions = RTEMS_NO_WAIT;
     381                                        tty->rawInBufSemaphoreOptions = RTEMS_NO_WAIT;
    340382                                }
    341383                        }
     
    345387        rtems_semaphore_release (tty->osem);
    346388        return sc;
     389}
     390
     391/*
     392 * Send characters to device-specific code
     393 */
     394static void
     395osend (const char *buf, int len, struct rtems_termios_tty *tty)
     396{
     397        unsigned int newHead;
     398        rtems_interrupt_level level;
     399        rtems_status_code sc;
     400
     401        if (!tty->outputUsesInterrupts) {
     402                (*tty->write)(tty->minor, buf, len);
     403                return;
     404        }
     405        newHead = tty->rawOutBufHead;
     406        while (len) {
     407                /*
     408                 * Performance improvement could be made here.
     409                 * Copy multiple bytes to raw buffer:
     410                 * if (len > 1) && (space to buffer end, or tail > 1)
     411                 *      ncopy = MIN (len, space to buffer end or tail)
     412                 *      memcpy (raw buffer, buf, ncopy)
     413                 *      buf += ncopy
     414                 *      len -= ncopy
     415                 *
     416                 * To minimize latency, the memcpy should be done
     417                 * with interrupts enabled.
     418                 */
     419                newHead = (newHead + 1) % RAW_OUTPUT_BUFFER_SIZE;
     420                rtems_interrupt_disable (level);
     421                while (newHead == tty->rawOutBufTail) {
     422                        tty->rawOutBufState = rob_wait;
     423                        rtems_interrupt_enable (level);
     424                        sc = rtems_semaphore_obtain (tty->rawOutBufSemaphore,
     425                                                        RTEMS_WAIT,
     426                                                        RTEMS_NO_TIMEOUT);
     427                        if (sc != RTEMS_SUCCESSFUL)
     428                                rtems_fatal_error_occurred (sc);
     429                        rtems_interrupt_disable (level);
     430                }
     431                tty->rawOutBuf[tty->rawOutBufHead] = *buf++;
     432                tty->rawOutBufHead = newHead;
     433                if (tty->rawOutBufState == rob_idle) {
     434                        rtems_interrupt_enable (level);
     435                        tty->rawOutBufState = rob_busy;
     436                        (*tty->write)(tty->minor, (char *)&tty->rawOutBuf[tty->rawOutBufTail], 1);
     437                }
     438                else {
     439                        rtems_interrupt_enable (level);
     440                }
     441                len--;
     442        }
    347443}
    348444
     
    361457                                tty->column = 0;
    362458                        if (tty->termios.c_oflag & ONLCR) {
    363                                 (*tty->write)(tty->minor, "\r", 1);
     459                                osend ("\r", 1, tty);
    364460                                tty->column = 0;
    365461                        }
     
    382478                        if ((tty->termios.c_oflag & TABDLY) == XTABS) {
    383479                                tty->column += i;
    384                                 (*tty->write)(tty->minor,  "        ",  i);
     480                                osend ( "        ",  i, tty);
    385481                                return;
    386482                        }
     
    401497                }
    402498        }
    403         (*tty->write)(tty->minor, &c, 1);
     499        osend (&c, 1, tty);
    404500}
    405501
     
    422518        }
    423519        else {
    424                 if ((*tty->write)(tty->minor, args->buffer, args->count) < 0)
    425                         sc = RTEMS_UNSATISFIED;
    426                 else
    427                         args->bytes_moved = args->count;
     520                osend (args->buffer, args->count, tty);
     521                args->bytes_moved = args->count;
    428522        }
    429523        rtems_semaphore_release (tty->osem);
     
    442536                echobuf[0] = '^';
    443537                echobuf[1] = c ^ 0x40;
    444                 (*tty->write)(tty->minor, echobuf, 2);
     538                osend (echobuf, 2, tty);
    445539                tty->column += 2;
    446540        }
     
    505599                                 */
    506600                                while (tty->column > col) {
    507                                         (*tty->write)(tty->minor, "\b", 1);
     601                                        osend ("\b", 1, tty);
    508602                                        tty->column--;
    509603                                }
     
    511605                        else {
    512606                                if (iscntrl (c) && (tty->termios.c_lflag & ECHOCTL)) {
    513                                         (*tty->write)(tty->minor, "\b \b", 3);
     607                                        osend ("\b \b", 3, tty);
    514608                                        if (tty->column)
    515609                                                tty->column--;
    516610                                }
    517611                                if (!iscntrl (c) || (tty->termios.c_lflag & ECHOCTL)) {
    518                                         (*tty->write)(tty->minor, "\b \b", 3);
     612                                        osend ("\b \b", 3, tty);
    519613                                        if (tty->column)
    520614                                                tty->column--;
     
    669763fillBufferQueue (struct rtems_termios_tty *tty)
    670764{
    671         rtems_interval timeout = tty->rawBufSemaphoreFirstTimeout;
     765        rtems_interval timeout = tty->rawInBufSemaphoreFirstTimeout;
    672766        rtems_status_code sc;
    673767
     
    676770                 * Process characters read from raw queue
    677771                 */
    678                 while (tty->rawBufHead != tty->rawBufTail) {
     772                while (tty->rawInBufHead != tty->rawInBufTail) {
    679773                        unsigned char c;
    680774                        unsigned int newHead;
    681775
    682                         newHead = (tty->rawBufHead + 1) % RAW_BUFFER_SIZE;
    683                         c = tty->rawBuf[newHead];
    684                         tty->rawBufHead = newHead;
     776                        newHead = (tty->rawInBufHead + 1) % RAW_INPUT_BUFFER_SIZE;
     777                        c = tty->rawInBuf[newHead];
     778                        tty->rawInBufHead = newHead;
    685779                        if (tty->termios.c_lflag & ICANON) {
    686780                                if  (siproc (c, tty))
     
    692786                                        return RTEMS_SUCCESSFUL;
    693787                        }
    694                         timeout = tty->rawBufSemaphoreTimeout;
     788                        timeout = tty->rawInBufSemaphoreTimeout;
    695789                }
    696790
     
    698792                 * Wait for characters
    699793                 */
    700                 sc = rtems_semaphore_obtain (tty->rawBufSemaphore,
    701                                                 tty->rawBufSemaphoreOptions,
     794                sc = rtems_semaphore_obtain (tty->rawInBufSemaphore,
     795                                                tty->rawInBufSemaphoreOptions,
    702796                                                timeout);
    703797                if (sc != RTEMS_SUCCESSFUL)
     
    740834/*
    741835 * Place characters on raw queue.
    742  * NOTE: This routine runs in the context of the device interrupt handler.
     836 * NOTE: This routine runs in the context of the
     837 *       device receive interrupt handler.
    743838 */
    744839void
     
    749844
    750845        while (len) {
    751                 newTail = (tty->rawBufTail + 1) % RAW_BUFFER_SIZE;
    752                 if (newTail == tty->rawBufHead) {
    753                         tty->rawBufDropped += len;
     846                newTail = (tty->rawInBufTail + 1) % RAW_INPUT_BUFFER_SIZE;
     847                if (newTail == tty->rawInBufHead) {
     848                        tty->rawInBufDropped += len;
    754849                        break;
    755850                }
    756                 tty->rawBuf[newTail] = *buf++;
     851                tty->rawInBuf[newTail] = *buf++;
    757852                len--;
    758                 tty->rawBufTail = newTail;
    759         }
    760         rtems_semaphore_release (tty->rawBufSemaphore);
    761 }
    762 
    763 /*
    764  *  Reserve enough resources to open every physical device once.
    765  */
    766 
    767 void 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 }
     853                tty->rawInBufTail = newTail;
     854        }
     855        rtems_semaphore_release (tty->rawInBufSemaphore);
     856}
     857
     858/*
     859 * Characters have been transmitted
     860 * NOTE: This routine runs in the context of the
     861 *       device transmit interrupt handler.
     862 * The second argument is the number of characters transmitted so far.
     863 * This value will always be 1 for devices which generate an interrupt
     864 * for each transmitted character.
     865 */
     866void
     867rtems_termios_dequeue_characters (void *ttyp, int len)
     868{
     869        struct rtems_termios_tty *tty = ttyp;
     870        unsigned int newTail;
     871        int nToSend;
     872
     873        if (tty->rawOutBufState == rob_wait)
     874                rtems_semaphore_release (tty->rawOutBufSemaphore);
     875        newTail = (tty->rawOutBufTail + len) % RAW_OUTPUT_BUFFER_SIZE;
     876        if (newTail == tty->rawOutBufHead) {
     877                /*
     878                 * Buffer empty
     879                 */
     880                tty->rawOutBufState = rob_idle;
     881        }
     882        else {
     883                /*
     884                 * Buffer not empty, start tranmitter
     885                 */
     886                tty->rawOutBufState = rob_busy;
     887                if (newTail > tty->rawOutBufHead)
     888                        nToSend = RAW_OUTPUT_BUFFER_SIZE - newTail;
     889                else
     890                        nToSend = tty->rawOutBufHead - newTail;
     891                (*tty->write)(tty->minor, (char *)&tty->rawOutBuf[newTail], nToSend);
     892        }
     893        tty->rawOutBufTail = newTail;
     894}
Note: See TracChangeset for help on using the changeset viewer.