Changeset 87894c0 in rtems for doc


Ignore:
Timestamp:
Jul 11, 2014, 11:29:53 AM (5 years ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
4.11, master
Children:
6b0a7efc
Parents:
742402b5
git-author:
Sebastian Huber <sebastian.huber@…> (07/11/14 11:29:53)
git-committer:
Sebastian Huber <sebastian.huber@…> (07/21/14 15:43:11)
Message:

doc: Update console driver documentation

File:
1 edited

Legend:

Unmodified
Added
Removed
  • doc/bsp_howto/console.t

    r742402b5 r87894c0  
    88@section Introduction
    99
    10 This chapter describes the operation of a console driver using 
     10This chapter describes the operation of a console driver using
    1111the RTEMS POSIX Termios support.  Traditionally RTEMS has referred
    1212to all serial device drivers as console device drivers.  A
     
    1717The serial driver may be called as the consequence of a C Library
    1818call such as @code{printf} or @code{scanf} or directly via the
    19 @code{read} or @code{write} system calls. 
    20 There are two main functioning modes: 
     19@code{read} or @code{write} system calls.
     20There are two main functioning modes:
    2121
    2222@itemize @bullet
     
    2525line, tabulations, etc.) recognition and processing,
    2626
    27 @item raw: permits raw data processing. 
     27@item raw: permits raw data processing.
    2828
    2929@end itemize
    3030
    3131One may think that two serial drivers are needed to handle these two types
    32 of data, but Termios permits having only one driver. 
     32of data, but Termios permits having only one driver.
    3333
    3434@section Termios
     
    3939Open Group has the termios portion of the POSIX standard online
    4040at @uref{http://opengroup.org/onlinepubs/007908775/xbd/termios.html
    41 ,http://opengroup.org/onlinepubs/007908775/xbd/termios.html}. 
     41,http://opengroup.org/onlinepubs/007908775/xbd/termios.html}.
    4242The requirements for the @code{<termios.h>} file are also provided
    4343and are at @uref{http://opengroup.org/onlinepubs/007908775/xsh/termios.h.html,
     
    5050@item from the user's side because it provides standard primitive operations
    5151to access the terminal and change configuration settings.  These operations
    52 are the same under UNIX and RTEMS. 
     52are the same under UNIX and RTEMS.
    5353
    5454@item from the BSP developer's side because it frees the
    55 developer from dealing with buffer states and mutual exclusions on them. 
     55developer from dealing with buffer states and mutual exclusions on them.
    5656Early RTEMS console device drivers also did their own special
    5757character processing.
     
    6363@end itemize
    6464
    65 Termios support includes: 
     65Termios support includes:
    6666
    6767@itemize @bullet
     
    7070
    7171@item blocking or non-blocking characters receive, with or without
    72 Timeout. 
     72Timeout.
    7373
    7474@end itemize
     
    8282@section Driver Functioning Modes
    8383
    84 There are generally two main functioning modes for an UART (Universal
    85 Asynchronous Receiver-Transmitter, i.e. the serial chip): 
     84There are generally three main functioning modes for an UART (Universal
     85Asynchronous Receiver-Transmitter, i.e. the serial chip):
    8686
    8787@itemize @bullet
     
    8989@item polled mode
    9090@item interrupt driven mode
     91@item task driven mode
    9192
    9293@end itemize
    9394
    9495In polled mode, the processor blocks on sending/receiving characters.
    95 This mode is not the most efficient way to utilize the UART. But 
     96This mode is not the most efficient way to utilize the UART. But
    9697polled mode is usually necessary when one wants to print an
    9798error message in the event of a fatal error such as a fatal error
     
    121122The interrupt service routine has to send the characters
    122123remaining in the output buffer the same way.   When the transmitting side
    123 of the UART is idle, it is typically necessary to prime the transmitter 
     124of the UART is idle, it is typically necessary to prime the transmitter
    124125before the first interrupt will occur.
    125126
     127The task driven mode is similar to interrupt driven mode, but the actual data
     128processing is done in dedicated tasks instead of interrupt routines.
     129
    126130@section Serial Driver Functioning Overview
    127131
    128 The following Figure shows how a Termios driven serial driver works: 
     132The following Figure shows how a Termios driven serial driver works:
    129133
    130134@ifset use-ascii
     
    150154scanf, read, write, etc.),
    151155
    152 @item C library (e.g. RedHat (formerly Cygnus) Newlib) calls
     156@item C library (ctx.g. RedHat (formerly Cygnus) Newlib) calls
    153157the RTEMS system call interface.  This code can be found in the
    154 @code{cpukit/libcsupport/src} directory.
    155 
    156 @item Glue code calls the serial driver entry routines. 
     158@file{cpukit/libcsupport/src} directory.
     159
     160@item Glue code calls the serial driver entry routines.
    157161
    158162@end itemize
     
    160164@subsection Basics
    161165
    162 You need to include the following header files in your Termios device driver
    163 source file:
    164 @example
    165 @group
    166 #include <unistd.h>
    167 #include <termios.h>
    168 
    169 #include <rtems.h>
    170 #include <rtems/libio.h>
    171 #include <rtems/console.h>
    172 @end group
    173 @end example
    174 
    175 You need to provide a data structure for the Termios driver interface.  The
    176 functions are described later in this chapter.  The functions should return
    177 zero on succes and minus one in case of an error.  Currently the return value
    178 will be not checked from the Termios infrastructure in most cases.  One notable
    179 exception is the polled read function, here is the return value important.
    180 
    181 If you want to use polled IO it should look like the following.  You may also
    182 have a look at @code{c/src/lib/libbsp/shared/console-polled.c} for a shared
    183 implementation of the basic framework.  Termios must be told the addresses of
    184 the functions that are to be used for simple character IO, i.e. pointers to the
    185 @code{my_driver_poll_read} and @code{my_driver_poll_write} functions described
    186 later in @ref{Console Driver Termios and Polled IO}.
    187 
    188 @example
    189 @group
    190 static const rtems_termios_callbacks my_driver_callbacks_polled = @{
    191     .firstOpen = my_driver_first_open,
    192     .lastClose = my_driver_last_close,
    193     .pollRead = my_driver_poll_read,
    194     .write = my_driver_poll_write,
    195     .setAttributes = my_driver_set_attributes,
    196     .stopRemoteTx = NULL,
    197     .startRemoteTx = NULL,
    198     .outputUsesInterrupts = TERMIOS_POLLED
    199 @};
     166The low-level driver API changed between RTEMS 4.10 and RTEMS 4.11.  The legacy
     167callback API is still supported, but its use is discouraged.  The following
     168functions are deprecated:
     169
     170@itemize @bullet
     171
     172@item @code{rtems_termios_open()} - use @code{rtems_termios_device_open()} in
     173combination with @code{rtems_termios_device_install()} instead.
     174
     175@item @code{rtems_termios_close()} - use @code{rtems_termios_device_close()}
     176instead.
     177
     178@end itemize
     179
     180This manual describes the new API.  A new console driver should consist of
     181three parts.
     182
     183@enumerate
     184
     185@item The basic console driver functions using the Termios support.  Add this
     186the BSPs Makefile.am:
     187
     188@example
     189@group
     190[...]
     191libbsp_a_SOURCES += ../../shared/console-termios.c
     192[...]
     193@end group
     194@end example
     195
     196@item A general serial module specific low-level driver providing the handler
     197table for the Termios @code{rtems_termios_device_install()} function.  This
     198low-level driver could be used for more than one BSP.
     199
     200@item A BSP specific initialization routine @code{console_initialize()}, that
     201calls @code{rtems_termios_device_install()} providing a low-level driver
     202context for each installed device.
     203
     204@end enumerate
     205
     206You need to provide a device handler structure for the Termios device
     207interface.  The functions are described later in this chapter.  The first open
     208and set attributes handler return a boolean status to indicate success (true)
     209or failure (false).  The polled read function returns an unsigned character in
     210case one is available or minus one otherwise.
     211
     212If you want to use polled IO it should look like the following.  Termios must
     213be told the addresses of the handler that are to be used for simple character
     214IO, i.e. pointers to the @code{my_driver_poll_read()} and
     215@code{my_driver_poll_write()} functions described later in @ref{Console Driver
     216Termios and Polled IO}.
     217
     218@example
     219@group
     220const rtems_termios_handler my_driver_handler_polled = @{
     221  .first_open = my_driver_first_open,
     222  .last_close = my_driver_last_close,
     223  .poll_read = my_driver_poll_read,
     224  .write = my_driver_poll_write,
     225  .set_attributes = my_driver_set_attributes,
     226  .stop_remote_tx = NULL,
     227  .start_remote_tx = NULL,
     228  .mode = TERMIOS_POLLED
     229@}
    200230@end group
    201231@end example
     
    203233For an interrupt driven implementation you need the following.  The driver
    204234functioning is quite different in this mode.  There is no device driver read
    205 function to be passed to Termios.  Indeed a @code{console_read} call returns
    206 the contents of Termios input buffer.  This buffer is filled in the driver
    207 interrupt subroutine, see also
    208 @ref{Console Driver Termios and Interrupt Driven IO}.
    209 The driver is responsible for providing a pointer to the
    210 @code{my_driver_interrupt_write} function.
    211 
    212 @example
    213 @group
    214 static const rtems_termios_callbacks my_driver_callbacks_interrupt = @{
    215     .firstOpen = my_driver_first_open,
    216     .lastClose = my_driver_last_close,
    217     .pollRead = NULL,
    218     .write = my_driver_interrupt_write,
    219     .setAttributes = my_driver_set_attributes,
    220     .stopRemoteTx = NULL,
    221     .startRemoteTx = NULL,
    222     .outputUsesInterrupts = TERMIOS_IRQ_DRIVEN
     235handler to be passed to Termios.  Indeed a @code{console_read()} call returns the
     236contents of Termios input buffer.  This buffer is filled in the driver
     237interrupt subroutine, see also @ref{Console Driver Termios and Interrupt Driven
     238IO}.  The driver is responsible for providing a pointer to the
     239@code{my_driver_interrupt_write()} function.
     240
     241@example
     242@group
     243const rtems_termios_handler my_driver_handler_interrupt = @{
     244  .first_open = my_driver_first_open,
     245  .last_close = my_driver_last_close,
     246  .poll_read = NULL,
     247  .write = my_driver_interrupt_write,
     248  .set_attributes = my_driver_set_attributes,
     249  .stopRemoteTx = NULL,
     250  .stop_remote_tx = NULL,
     251  .start_remote_tx = NULL,
     252  .mode = TERMIOS_IRQ_DRIVEN
    223253@};
    224254@end group
    225255@end example
    226256
    227 You can also provide callback functions for remote transmission control.  This
    228 is not covered in this manual, so thay are set to @code{NULL} in the above
     257You can also provide hander for remote transmission control.  This
     258is not covered in this manual, so they are set to @code{NULL} in the above
    229259examples.
    230260
    231 Normally the device specific data structures are stored in a table which is
    232 indexed by the minor number.  You may need an entry for the Termios handler
    233 pointer in your data structure.  For simplicity of the console initialization
    234 example the device name is also present.
    235 
    236 @example
    237 @group
    238 /* Driver specific data structure */
     261The low-level driver should provide a data structure for its device context.
     262The initialization routine must provide a context for each installed device via
     263@code{rtems_termios_device_install()}.  For simplicity of the console
     264initialization example the device name is also present.  Her is an example header file.
     265
     266@example
     267@group
     268#ifndef MY_DRIVER_H
     269#define MY_DRIVER_H
     270
     271#include <rtems/termiostypes.h>
     272
     273#include <some-chip-header.h>
     274
     275/* Low-level driver specific data structure */
    239276typedef struct @{
    240     const char *device_name;
    241     struct rtems_termios_tty *tty;
    242 @} my_driver_entry;
    243 
    244 /*
    245  * This table contains the driver specific data.  It is later
    246  * indexed by the minor number.
    247  */
    248 static my_driver_entry my_driver_table [MY_DRIVER_DEVICE_NUMBER];
     277  const char *device_name;
     278  volatile module_register_block *regs;
     279  /* More stuff */
     280@} my_driver_context;
     281
     282extern const rtems_termios_handler my_driver_handler_polled;
     283
     284extern const rtems_termios_handler my_driver_handler_interrupt;
     285
     286#endif /* MY_DRIVER_H */
    249287@end group
    250288@end example
     
    252290@subsection Termios and Polled IO
    253291
    254 The following functions are provided by the driver and invoked by
     292The following handler are provided by the low-level driver and invoked by
    255293Termios for simple character IO.
    256294
    257 The @code{my_driver_poll_write} routine is responsible for writing @code{n}
    258 characters from @code{buf} to the serial device specified by @code{minor}.
    259 
    260 On success, the number of bytes written is returned (zero indicates nothing
    261 was written).  On error, @code{-1} is returned.
    262 
    263 NOTE: Due to the current implementation of termios, any data passed into
    264   the write function will be lost.
    265 
    266 @example
    267 @group
    268 static ssize_t my_driver_poll_write(int minor, const char *buf, size_t n)
    269 @{
    270     my_driver_entry *e = &my_driver_table [minor];
    271     int i = 0;
    272    
    273     /*
    274      * There is no need to check the minor number since it is derived
    275      * from a file descriptor.  The upper layer takes care that it is
    276      * in a valid range.
    277      */
    278    
    279     /* Write */
    280     for (i = 0; i < n; ++i) @{
    281         my_driver_write_char(e, buf [i]);
    282     @}
    283    
    284     return n;
     295The @code{my_driver_poll_write()} routine is responsible for writing @code{n}
     296characters from @code{buf} to the serial device specified by @code{tty}.
     297
     298@example
     299@group
     300static void my_driver_poll_write(
     301  rtems_termios_tty *tty,
     302  const char        *buf,
     303  size_t             n
     304)
     305@{
     306  my_driver_context *ctx = rtems_termios_get_device_context(tty);
     307  size_t i;
     308
     309  /* Write */
     310  for (i = 0; i < n; ++i) @{
     311    my_driver_write_char(ctx, buf[i]);
     312  @}
    285313@}
    286314@end group
     
    288316
    289317The @code{my_driver_poll_read} routine is responsible for reading a single
    290 character from the serial device specified by @code{minor}.  If no character is
     318character from the serial device specified by @code{tty}.  If no character is
    291319available, then the routine should return minus one.
    292320
    293321@example
    294322@group
    295 static int my_driver_poll_read(int minor)
    296 @{
    297     my_driver_entry *e = &my_driver_table [minor];
    298    
    299     /*
    300      * There is no need to check the minor number since it is derived
    301      * from a file descriptor.  The upper layer takes care that it is
    302      * in a valid range.
    303      */
    304 
    305     /* Check if a character is available */
    306     if (my_driver_can_read_char(e)) @{
    307         /* Return the character */
    308         return my_driver_read_char(e);
    309     @} else @{
    310         /* Return an error status */
    311         return -1;
    312     @}
     323static int my_driver_poll_read(rtems_termios_tty *tty)
     324@{
     325  my_driver_context *ctx = rtems_termios_get_device_context(tty);
     326
     327  /* Check if a character is available */
     328  if (my_driver_can_read_char(ctx)) @{
     329    /* Return the character */
     330    return my_driver_read_char(ctx);
     331  @} else @{
     332    /* Return an error status */
     333    return -1;
     334  @}
    313335@}
    314336@end group
     
    321343the driver.
    322344
    323 The @code{my_driver_interrupt_handler} is responsible for processing
     345The @code{my_driver_interrupt_handler()} is responsible for processing
    324346asynchronous interrupts from the UART.  There may be multiple interrupt
    325347handlers for a single UART.  Some UARTs can generate a unique interrupt vector
     
    327349transmitter is ready for another character.
    328350
    329 In the simplest case, the @code{my_driver_interrupt_handler} will have to check
     351In the simplest case, the @code{my_driver_interrupt_handler()} will have to check
    330352the status of the UART and determine what caused the interrupt.  The following
    331353describes the operation of an @code{my_driver_interrupt_handler} which has to
     
    335357@group
    336358static void my_driver_interrupt_handler(
    337     rtems_vector_number vector,
    338     void *arg
     359  rtems_vector_number vector,
     360  void                *arg
    339361)
    340362@{
    341     my_driver_entry *e = (my_driver_entry *) arg;
    342     char buf [N];
    343     int n = 0;
    344 
     363  rtems_termios_tty *tty = arg;
     364  my_driver_context *ctx = rtems_termios_get_device_context(tty);
     365  char buf[N];
     366  size_t n;
     367
     368  /*
     369   * Check if we have received something.  The function reads the
     370   * received characters from the device and stores them in the
     371   * buffer.  It returns the number of read characters.
     372   */
     373  n = my_driver_read_received_chars(ctx, buf, N);
     374  if (n > 0) @{
     375    /* Hand the data over to the Termios infrastructure */
     376    rtems_termios_enqueue_raw_characters(tty, buf, n);
     377  @}
     378
     379  /*
     380   * Check if we have something transmitted.  The functions returns
     381   * the number of transmitted characters since the last write to the
     382   * device.
     383   */
     384  n = my_driver_transmitted_chars(ctx);
     385  if (n > 0) @{
    345386    /*
    346      * Check if we have received something.  The function reads the
    347      * received characters from the device and stores them in the
    348      * buffer.  It returns the number of read characters.
     387     * Notify Termios that we have transmitted some characters.  It
     388     * will call now the interrupt write function if more characters
     389     * are ready for transmission.
    349390     */
    350     n = my_driver_read_received_chars(e, buf, N);
    351     if (n > 0) @{
    352         /* Hand the data over to the Termios infrastructure */
    353         rtems_termios_enqueue_raw_characters(e->tty, buf, n);
    354     @}
    355 
    356     /*
    357      * Check if we have something transmitted.  The functions returns
    358      * the number of transmitted characters since the last write to the
    359      * device.
    360      */
    361     n = my_driver_transmitted_chars(e);
    362     if (n > 0) @{
    363         /*
    364          * Notify Termios that we have transmitted some characters.  It
    365          * will call now the interrupt write function if more characters
    366          * are ready for transmission.
    367          */
    368         rtems_termios_dequeue_characters(e->tty, n);
    369     @}
    370 @}
    371 @end group
    372 @end example
    373 
    374 The @code{my_driver_interrupt_write} function is responsible for telling the
    375 device that the @code{n} characters at @code{buf} are to be transmitted.  The
    376 return value may be arbitrary since it is not checked from Termios.  It is
    377 guaranteed that @code{n} is greater than zero.  This routine is invoked either
    378 from task context with disabled interrupts to start a new transmission process
    379 with exactly one character in case of an idle output state or from the
     391    rtems_termios_dequeue_characters(tty, n);
     392  @}
     393@}
     394@end group
     395@end example
     396
     397The @code{my_driver_interrupt_write()} function is responsible for telling the
     398device that the @code{n} characters at @code{buf} are to be transmitted.  It
     399the value @code{n} is zero to indicate that no more characters are to send.
     400The driver can disable the transmit interrupts now.  This routine is invoked
     401either from task context with disabled interrupts to start a new transmission
     402process with exactly one character in case of an idle output state or from the
    380403interrupt handler to refill the transmitter.  If the routine is invoked to
    381404start the transmit process the output state will become busy and Termios starts
     
    384407character.
    385408
    386 On error, the function should return @code{-1}. On success, it should return
    387 @code{0}, since it the interrupt handler will report the actual number of
    388 characters transmitted.
    389  
    390 @example
    391 @group
    392 static ssize_t my_driver_interrupt_write(int minor, const char *buf, size_t n)
    393 @{
    394     my_driver_entry *e = &my_driver_table [minor];
    395    
     409@example
     410@group
     411static void my_driver_interrupt_write(
     412  rtems_termios_tty *tty,
     413  const char        *buf,
     414  size_t             n
     415)
     416@{
     417  my_driver_context *ctx = rtems_termios_get_device_context(tty);
     418
     419  /*
     420   * Tell the device to transmit some characters from buf (less than
     421   * or equal to n).  When the device is finished it should raise an
     422   * interrupt.  The interrupt handler will notify Termios that these
     423   * characters have been transmitted and this may trigger this write
     424   * function again.  You may have to store the number of outstanding
     425   * characters in the device data structure.
     426   */
     427
     428  /*
     429   * Termios will set n to zero to indicate that the transmitter is
     430   * now inactive.  The output buffer is empty in this case.  The
     431   * driver may disable the transmit interrupts now.
     432   */
     433@}
     434@end group
     435@end example
     436
     437@subsection Initialization
     438
     439The BSP specific driver initialization is called once during the RTEMS
     440initialization process.
     441
     442The @code{console_initialize()} function may look like this:
     443
     444@example
     445@group
     446#include <my-driver.h>
     447#include <rtems/console.h>
     448#include <bsp.h>
     449#include <bsp/fatal.h>
     450
     451static my_driver_context driver_context_table[M] = @{ /* Some values */ @};
     452
     453rtems_device_driver console_initialize(
     454  rtems_device_major_number  major,
     455  rtems_device_minor_number  minor,
     456  void                      *arg
     457)
     458@{
     459  rtems_status_code sc;
     460#ifdef SOME_BSP_USE_INTERRUPTS
     461  const rtems_termios_handler *handler = &my_driver_handler_interrupt;
     462#else
     463  const rtems_termios_handler *handler = &my_driver_handler_polled;
     464#endif
     465
     466  /*
     467   * Initialize the Termios infrastructure.  If Termios has already
     468   * been initialized by another device driver, then this call will
     469   * have no effect.
     470   */
     471  rtems_termios_initialize();
     472
     473  /* Initialize each device */
     474  for (
     475    minor = 0;
     476    minor < RTEMS_ARRAY_SIZE(driver_context_table);
     477    ++minor
     478  ) @{
     479    my_driver_context *ctx = &driver_context_table[minor];
     480
    396481    /*
    397      * There is no need to check the minor number since it is derived
    398      * from a file descriptor.  The upper layer takes care that it is
    399      * in a valid range.
     482     * Install this device in the file system and Termios.  In order
     483     * to use the console (i.e. being able to do printf, scanf etc.
     484     * on stdin, stdout and stderr), one device must be registered as
     485     * "/dev/console" (CONSOLE_DEVICE_NAME).
    400486     */
    401 
    402     /*
    403      * Tell the device to transmit some characters from buf (less than
    404      * or equal to n).  When the device is finished it should raise an
    405      * interrupt.  The interrupt handler will notify Termios that these
    406      * characters have been transmitted and this may trigger this write
    407      * function again.  You may have to store the number of outstanding
    408      * characters in the device data structure.
    409      */
    410 
    411     /*
    412      * Termios will set n to zero to indicate that the transmitter is
    413      * now inactive.  The output buffer is empty in this case.  The
    414      * driver may disable the transmit interrupts now.
    415      */
    416 
    417     return 0;
    418 @}
    419 @end group
    420 @end example
    421 
    422 @subsection Initialization
    423 
    424 The driver initialization is called once during the RTEMS initialization
    425 process.
    426 
    427 The @code{console_initialize} function may look like this:
    428 
    429 @example
    430 @group
    431 rtems_device_driver console_initialize(
    432     rtems_device_major_number major,
    433     rtems_device_minor_number minor,
    434     void *arg
     487    sc = rtems_termios_device_install(
     488      ctx->device_name,
     489      major,
     490      minor,
     491      handler,
     492      ctx
     493    );
     494    if (sc != RTEMS_SUCCESSFUL) @{
     495      bsp_fatal(SOME_BSP_FATAL_CONSOLE_DEVICE_INSTALL);
     496    @}
     497  @}
     498
     499  return RTEMS_SUCCESSFUL;
     500@}
     501@end group
     502@end example
     503
     504@subsection Opening a serial device
     505
     506The @code{console_open()} function provided by @file{console-termios.c} is
     507called whenever a serial device is opened.  The device registered as
     508@code{"/dev/console"} (@code{CONSOLE_DEVICE_NAME}) is opened automatically
     509during RTEMS initialization.  For instance, if UART channel 2 is registered as
     510@code{"/dev/tty1"}, the @code{console_open()} entry point will be called as the
     511result of an @code{fopen("/dev/tty1", mode)} in the application.
     512
     513During the first open of the device Termios will call the
     514@code{my_driver_first_open()} handler.
     515
     516@example
     517@group
     518static bool my_driver_first_open(
     519  rtems_termios_tty             *tty,
     520  rtems_libio_open_close_args_t *args
    435521)
    436522@{
    437     rtems_status_code sc = RTEMS_SUCCESSFUL;
    438     rtems_device_minor_number i = 0;
    439 
    440     /*
    441      * Initialize the Termios infrastructure.  If Termios has already
    442      * been initialized by another device driver, then this call will
    443      * have no effect.
    444      */
    445     rtems_termios_initialize();
    446    
    447     /* Initialize each device */
    448     for (i = 0; i < MY_DRIVER_DEVICE_NUMBER; ++i) @{
    449         my_driver_entry *e = &my_driver_table [i];
    450 
    451         /*
    452          * Register this device in the file system.  In order to use the
    453          * console (i.e. being able to do printf, scanf etc. on stdin,
    454          * stdout and stderr), some device must be registered
    455          * as "/dev/console" (CONSOLE_DEVICE_NAME).
    456          */
    457         sc = rtems_io_register_name (e->device_name, major, i);
    458         RTEMS_CHECK_SC(sc, "Register IO device");
    459 
    460         /*
    461          * Initialize this device and install the interrupt handler if
    462          * necessary.  You may also initialize the device in the first
    463          * open call.
    464          */
    465     @}
    466 
    467     return RTEMS_SUCCESSFUL;
    468 @}
    469 @end group
    470 @end example
    471 
    472 @subsection Opening a serial device
    473 
    474 The @code{console_open} function is called whenever a serial device is opened.
    475 The device registered as @code{"/dev/console"} (@code{CONSOLE_DEVICE_NAME}) is
    476 opened automatically during RTEMS initialization.  For instance, if UART
    477 channel 2 is registered as "/dev/tty1", the @code{console_open} entry point
    478 will be called as the result of an @code{fopen("/dev/tty1", mode)} in the
    479 application.
    480 
    481 The @code{console_open} function has to inform Termios of the low-level
    482 functions for serial line support.
    483 
    484 @example
    485 @group
    486 rtems_device_driver console_open(
    487     rtems_device_major_number major,
    488     rtems_device_minor_number minor,
    489     void *arg
     523  my_driver_context *ctx = rtems_termios_get_device_context(tty);
     524  rtems_status_code sc;
     525  bool ok;
     526
     527  /*
     528   * You may add some initialization code here.
     529   */
     530
     531  /*
     532   * Sets the initial baud rate.  This should be set to the value of
     533   * the boot loader.  This function accepts only exact Termios baud
     534   * values.
     535   */
     536  sc = rtems_termios_set_initial_baud(tty, MY_DRIVER_BAUD_RATE);
     537  if (sc != RTEMS_SUCCESSFUL) @{
     538    /* Not a valid Termios baud */
     539  @}
     540
     541  /*
     542   * Alternatively you can set the best baud.
     543   */
     544  rtems_termios_set_best_baud(tty, MY_DRIVER_BAUD_RATE);
     545
     546  /*
     547   * To propagate the initial Termios attributes to the device use
     548   * this.
     549   */
     550  ok = my_driver_set_attributes(tty, rtems_termios_get_termios(tty));
     551  if (!ok) @{
     552    /* This is bad */
     553  @}
     554
     555  /*
     556   * Return true to indicate a successful set attributes, and false
     557   * otherwise.
     558   */
     559  return true;
     560@}
     561@end group
     562@end example
     563
     564@subsection Closing a Serial Device
     565
     566The @code{console_close()} provided by @file{console-termios.c} is invoked when
     567the serial device is to be closed.  This entry point corresponds to the device
     568driver close entry point.
     569
     570Termios will call the @code{my_driver_last_close()} handler if the last close
     571happens on the device.
     572@example
     573@group
     574static void my_driver_last_close(
     575  rtems_termios_tty             *tty,
     576  rtems_libio_open_close_args_t *args
    490577)
    491578@{
    492     struct rtems_termios_callbacks *callbacks =
    493         &my_driver_callbacks_polled;
    494 
    495     /*
    496      * Check the minor number.  Termios does currently not check
    497      * the return value of the first open call so the minor
    498      * number must be checked here.
    499      */
    500     if (MY_DRIVER_IS_MINOR_INVALID(minor)) @{
    501         return RTEMS_INVALID_NUMBER;
    502     @}
    503 
    504     /*
    505      * Depending on the IO mode you need to pass a different set of
    506      * callback functions to Termios.
    507      */
    508     if (MY_DRIVER_USES_INTERRUPTS(minor)) @{
    509         callbacks = &my_driver_callbacks_interrupt;
    510     @}
    511 
    512     return rtems_termios_open(major, minor, arg, callbacks);
    513 @}
    514 @end group
    515 @end example
    516 
    517 During the first open of the device Termios will call @code{my_driver_first_open}.
    518 
    519 @example
    520 @group
    521 static int my_driver_first_open(int major, int minor, void *arg)
    522 @{
    523     my_driver_entry *e = &my_driver_table [minor];
    524     struct rtems_termios_tty *tty =
    525         ((rtems_libio_open_close_args_t *) arg)->iop->data1;
    526    
    527     /* Check minor number */
    528     if (MY_DRIVER_IS_MINOR_INVALID(minor)) @{
    529         return -1;
    530     @}
    531 
    532     /* Connect the TTY data structure */
    533     e->tty = tty;
    534 
    535     /*
    536      * You may add some initialization code here.
    537      */
    538 
    539     /*
    540      * Sets the inital baud rate.  This should be set to the value of
    541      * the boot loader.
    542      */
    543     return rtems_termios_set_initial_baud(e->tty, MY_DRIVER_BAUD_RATE);
    544 @}
    545 @end group
    546 @end example
    547 
    548 @subsection Closing a Serial Device
    549 
    550 The @code{console_close} is invoked when the serial device is to be closed.
    551 This entry point corresponds to the device driver close entry point.
    552 
    553 This routine is responsible for notifying Termios that the serial device was
    554 closed.  This is done with a call to @code{rtems_termios_close}.
    555 
    556 @example
    557 @group
    558 rtems_device_driver console_close(
    559     rtems_device_major_number major,
    560     rtems_device_minor_number minor,
    561     void *arg
     579  my_driver_context *ctx = rtems_termios_get_device_context(tty);
     580
     581  /*
     582   * The driver may do some cleanup here.
     583   */
     584@}
     585@end group
     586@end example
     587
     588@subsection Reading Characters from a Serial Device
     589
     590The @code{console_read()} provided by @file{console-termios.c} is invoked when
     591the serial device is to be read from.  This entry point corresponds to the
     592device driver read entry point.
     593
     594@subsection Writing Characters to a Serial Device
     595
     596The @code{console_write()} provided by @file{console-termios.c} is invoked when
     597the serial device is to be written to.  This entry point corresponds to the
     598device driver write entry point.
     599
     600@subsection Changing Serial Line Parameters
     601
     602The @code{console_control()} provided by @file{console-termios.c} is invoked
     603when the line parameters for a particular serial device are to be changed.
     604This entry point corresponds to the device driver IO control entry point.
     605
     606The application writer is able to control the serial line configuration with
     607Termios calls (such as the @code{ioctl()} command, see the Termios
     608documentation for more details).  If the driver is to support dynamic
     609configuration, then it must have the @code{console_control()} piece of code.
     610Basically @code{ioctl()} commands call @code{console_control()} with the serial
     611line configuration in a Termios defined data structure.
     612
     613The driver is responsible for reinitializing the device with the correct
     614settings.  For this purpose Termios calls the @code{my_driver_set_attributes()}
     615handler.
     616
     617@example
     618@group
     619static bool my_driver_set_attributes(
     620  rtems_termios_tty    *tty,
     621  const struct termios *term
    562622)
    563623@{
    564     return rtems_termios_close(arg);
    565 @}
    566 @end group
    567 @end example
    568 
    569 Termios will call the @code{my_driver_last_close} function if the last close
    570 happens on the device.
    571 @example
    572 @group
    573 static int my_driver_last_close(int major, int minor, void *arg)
    574 @{
    575     my_driver_entry *e = &my_driver_table [minor];
    576    
    577     /*
    578      * There is no need to check the minor number since it is derived
    579      * from a file descriptor.  The upper layer takes care that it is
    580      * in a valid range.
    581      */
    582 
    583     /* Disconnect the TTY data structure */
    584     e->tty = NULL;
    585 
    586     /*
    587      * The driver may do some cleanup here.
    588      */
    589 
    590     return 0;
    591 @}
    592 @end group
    593 @end example
    594 
    595 @subsection Reading Characters from a Serial Device
    596 
    597 The @code{console_read} is invoked when the serial device is to be read from.
    598 This entry point corresponds to the device driver read entry point.
    599 
    600 This routine is responsible for returning the content of the Termios input
    601 buffer.  This is done by invoking the @code{rtems_termios_read} routine.
    602 
    603 @example
    604 @group
    605 rtems_device_driver console_read(
    606     rtems_device_major_number major,
    607     rtems_device_minor_number minor,
    608     void *arg
    609 )
    610 @{
    611     return rtems_termios_read(arg);
    612 @}
    613 @end group
    614 @end example
    615 
    616 @subsection Writing Characters to a Serial Device
    617 
    618 The @code{console_write} is invoked when the serial device is to be written to.
    619 This entry point corresponds to the device driver write entry point.
    620 
    621 This routine is responsible for adding the requested characters to the Termios
    622 output queue for this device.  This is done by calling the routine
    623 @code{rtems_termios_write} to add the characters at the end of the Termios
    624 output buffer.
    625 
    626 @example
    627 @group
    628 rtems_device_driver console_write(
    629     rtems_device_major_number major,
    630     rtems_device_minor_number minor,
    631     void *arg
    632 )
    633 @{
    634     return rtems_termios_write(arg);
    635 @}
    636 @end group
    637 @end example
    638 
    639 @subsection Changing Serial Line Parameters
    640 
    641 The @code{console_control} is invoked when the line parameters for a particular
    642 serial device are to be changed.  This entry point corresponds to the device
    643 driver io_control entry point.
    644 
    645 The application writer is able to control the serial line configuration with
    646 Termios calls (such as the @code{ioctl} command, see the Termios documentation
    647 for more details).  If the driver is to support dynamic configuration, then it
    648 must have the @code{console_control} piece of code.  Basically @code{ioctl}
    649 commands call @code{console_control} with the serial line configuration in a
    650 Termios defined data structure.
    651 
    652 @example
    653 @group
    654 rtems_device_driver console_control(
    655     rtems_device_major_number major,
    656     rtems_device_minor_number minor,
    657     void *arg
    658 )
    659 @{
    660     return rtems_termios_ioctl(arg);
    661 @}
    662 @end group
    663 @end example
    664 
    665 The driver is responsible for reinitializing the device with the correct
    666 settings.  For this purpuse Termios calls the @code{my_driver_set_attributes}
    667 function.
    668 
    669 @example
    670 @group
    671 static int my_driver_set_attributes(
    672     int minor,
    673     const struct termios *t
    674 )
    675 @{
    676     my_driver_entry *e = &my_driver_table [minor];
    677    
    678     /*
    679      * There is no need to check the minor number since it is derived
    680      * from a file descriptor.  The upper layer takes care that it is
    681      * in a valid range.
    682      */
    683 
    684     /*
    685      * Inspect the termios data structure and configure the device
    686      * appropriately.  The driver should only be concerned with the
    687      * parts of the structure that specify hardware setting for the
    688      * communications channel such as baud, character size, etc.
    689      */
    690 
    691     return 0;
    692 @}
    693 @end group
    694 @end example
     624  my_driver_context *ctx = rtems_termios_get_device_context(tty);
     625
     626  /*
     627   * Inspect the termios data structure and configure the device
     628   * appropriately.  The driver should only be concerned with the
     629   * parts of the structure that specify hardware setting for the
     630   * communications channel such as baud, character size, etc.
     631   */
     632
     633  /*
     634   * Return true to indicate a successful set attributes, and false
     635   * otherwise.
     636   */
     637  return true;
     638@}
     639@end group
     640@end example
Note: See TracChangeset for help on using the changeset viewer.