source: rtems/c/src/lib/libbsp/shared/console.c @ 1c6926c1

Last change on this file since 1c6926c1 was 1c6926c1, checked in by Kevin Kirspel <kevin-kirspel@…>, on Mar 21, 2017 at 7:39:48 PM

termios: Synchronize with latest FreeBSD headers

Adding modified FreeBSD headers to synchronize RTEMS termios with
FreeBSD. Modify termios to support dedicated input and output baud for
termios structure. Updated BSPs to use dedicated input and output baud
in termios structure. Updated tools to use dedicated input and output
baud in termios structure. Updated termios testsuites to use dedicated
input and output baud in termios structure.

Close #2897.

  • Property mode set to 100644
File size: 9.6 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup Console
5 *
6 * @brief Extension of the generic libchip console driver shell
7 */
8
9/*
10 *  COPYRIGHT (c) 1989-2011, 2016.
11 *  On-Line Applications Research Corporation (OAR).
12 *
13 *  The license and distribution terms for this file may be
14 *  found in the file LICENSE in this distribution or at
15 *  http://www.rtems.org/license/LICENSE.
16 */
17
18#include <bsp.h>
19#include <bsp/fatal.h>
20#include <rtems/libio.h>
21#include <rtems/console.h>
22#include <stdlib.h>
23#include <assert.h>
24#include <termios.h>
25
26#include <rtems/termiostypes.h>
27#include <libchip/serial.h>
28#include "console_private.h"
29
30unsigned long               Console_Port_Count  = 0;
31console_tbl               **Console_Port_Tbl    = NULL;
32console_data               *Console_Port_Data   = NULL;
33rtems_device_minor_number   Console_Port_Minor  = 0;
34static bool                 console_initialized = false;
35
36/*
37 *  console_find_console_entry
38 *
39 *  This method is used to search the console entries for a
40 *  specific device entry.
41 */
42console_tbl* console_find_console_entry(
43  const char                *match,
44  size_t                     length,
45  rtems_device_minor_number *match_minor
46)
47{
48  rtems_device_minor_number  minor;
49
50  /*
51   * The the match name is NULL get the minor number entry.
52   */
53  if (match == NULL) {
54    if (*match_minor < Console_Port_Count)
55      return Console_Port_Tbl[*match_minor];
56    return NULL;
57  }
58
59  for (minor=0; minor < Console_Port_Count ; minor++) {
60    console_tbl  *cptr = Console_Port_Tbl[minor];
61
62    /*
63     * Console table entries include /dev/ prefix, device names passed
64     * in on command line do not.
65     */
66    if ( !strncmp( cptr->sDeviceName, match, length ) ) {
67      *match_minor = minor;
68      return cptr;
69    }
70  }
71
72  return NULL;
73}
74
75/*
76 *  console_initialize_data
77 *
78 *  This method is used to initialize the table of pointers to the
79 *  serial port configuration structure entries.
80 */
81void console_initialize_data(void)
82{
83  int i;
84
85  if ( Console_Port_Tbl )
86    return;
87
88  /*
89   * Allocate memory for the table of device pointers.
90   */
91  Console_Port_Count = Console_Configuration_Count;
92  Console_Port_Tbl   = malloc( Console_Port_Count * sizeof( console_tbl * ) );
93  if (Console_Port_Tbl == NULL)
94    bsp_fatal( BSP_FATAL_CONSOLE_NO_MEMORY_0 );
95
96  /*
97   * Allocate memory for the table of device specific data pointers.
98   */
99  Console_Port_Data  = calloc( Console_Port_Count, sizeof( console_data ) );
100  if ( Console_Port_Data == NULL ) {
101    bsp_fatal( BSP_FATAL_CONSOLE_NO_MEMORY_3 );
102  }
103
104  /*
105   * Fill in the Console Table
106   */
107  for (i=0 ; i < Console_Port_Count ; i++) {
108    Console_Port_Tbl[i] = &Console_Configuration_Ports[i];
109  }
110}
111
112/*
113 *  console_register_devices
114 *
115 *  This method is used to add dynamically discovered devices to the
116 *  set of serial ports supported.
117 */
118void console_register_devices(
119  console_tbl *new_ports,
120  size_t       number_of_ports
121)
122{
123  int  old_number_of_ports;
124  int  i;
125
126  /*
127   * Initialize the console data elements
128   */
129  console_initialize_data();
130
131  /*
132   *  console_initialize() has been invoked so it is now too late to
133   *  register devices.
134   */
135  if ( console_initialized ) {
136    bsp_fatal( BSP_FATAL_CONSOLE_MULTI_INIT );
137  }
138
139  /*
140   *  Allocate memory for the console port extension
141   */
142  old_number_of_ports = Console_Port_Count;
143  Console_Port_Count += number_of_ports;
144  Console_Port_Tbl = realloc(
145    Console_Port_Tbl,
146    Console_Port_Count * sizeof(console_tbl *)
147  );
148  if ( Console_Port_Tbl == NULL ) {
149    bsp_fatal( BSP_FATAL_CONSOLE_NO_MEMORY_1 );
150  }
151
152  /*
153   * Since we can only add devices before console_initialize(),
154   * the data area will contain no information and must be zero
155   * before it is used. So extend the area and zero it out.
156   */
157  Console_Port_Data = realloc(
158    Console_Port_Data,
159    Console_Port_Count * sizeof(console_data)
160  );
161  if ( Console_Port_Data == NULL ) {
162    bsp_fatal( BSP_FATAL_CONSOLE_NO_MEMORY_2 );
163  }
164  memset(Console_Port_Data, '\0', Console_Port_Count * sizeof(console_data));
165
166  /*
167   *  Now add the new devices at the end.
168   */
169  for (i=0 ; i < number_of_ports ; i++) {
170    Console_Port_Tbl[old_number_of_ports + i]  = &new_ports[i];
171  }
172}
173
174/*
175 *  console_open
176 *
177 *  open a port as a termios console.
178 */
179rtems_device_driver console_open(
180  rtems_device_major_number major,
181  rtems_device_minor_number minor,
182  void                    * arg
183)
184{
185  rtems_status_code              status;
186  rtems_libio_open_close_args_t *args = arg;
187  rtems_libio_ioctl_args_t       IoctlArgs;
188  struct termios                 Termios;
189  rtems_termios_callbacks        Callbacks;
190  console_tbl                   *cptr;
191  struct rtems_termios_tty      *current_tty;
192
193  /*
194   * Verify the port number is valid.
195   */
196  if ( minor > Console_Port_Count ) {
197    return RTEMS_INVALID_NUMBER;
198  }
199
200  /*
201   * Open the port as a termios console driver.
202   */
203
204  cptr = Console_Port_Tbl[minor];
205  Callbacks.firstOpen            = cptr->pDeviceFns->deviceFirstOpen;
206  Callbacks.lastClose            = cptr->pDeviceFns->deviceLastClose;
207  Callbacks.pollRead             = cptr->pDeviceFns->deviceRead;
208  Callbacks.write                = cptr->pDeviceFns->deviceWrite;
209  Callbacks.setAttributes        = cptr->pDeviceFns->deviceSetAttributes;
210  if (cptr->pDeviceFlow != NULL) {
211    Callbacks.stopRemoteTx  = cptr->pDeviceFlow->deviceStopRemoteTx;
212    Callbacks.startRemoteTx = cptr->pDeviceFlow->deviceStartRemoteTx;
213  } else {
214    Callbacks.stopRemoteTx  = NULL;
215    Callbacks.startRemoteTx = NULL;
216  }
217  Callbacks.outputUsesInterrupts = cptr->pDeviceFns->deviceOutputUsesInterrupts;
218
219  /* XXX what about
220   *        Console_Port_Tbl[minor].ulMargin,
221   *        Console_Port_Tbl[minor].ulHysteresis);
222   */
223
224  status = rtems_termios_open( major, minor, arg, &Callbacks );
225  Console_Port_Data[minor].termios_data = args->iop->data1;
226
227  /* Get tty pointur from the Console_Port_Data */
228  current_tty = Console_Port_Data[minor].termios_data;
229
230  if ( (current_tty->refcount == 1) ) {
231
232    /*
233     *  If this BSP has a preferred default rate, then use that.
234     */
235    #if defined(BSP_DEFAULT_BAUD_RATE)
236      rtems_termios_set_initial_baud( current_tty, BSP_DEFAULT_BAUD_RATE );
237    #endif
238
239    /*
240     * If it's the first open, modified, if need, the port parameters
241     */
242    if ( minor != Console_Port_Minor ) {
243      /*
244       * If this is not the console we do not want ECHO and so forth
245       */
246      IoctlArgs.iop     = args->iop;
247      IoctlArgs.command = TIOCGETA;
248      IoctlArgs.buffer  = &Termios;
249      rtems_termios_ioctl( &IoctlArgs );
250
251      Termios.c_lflag   = ICANON;
252      IoctlArgs.command = TIOCSETA;
253      rtems_termios_ioctl( &IoctlArgs );
254    }
255  }
256
257  if ( (args->iop->flags&LIBIO_FLAGS_READ) &&
258      cptr->pDeviceFlow &&
259      cptr->pDeviceFlow->deviceStartRemoteTx) {
260    cptr->pDeviceFlow->deviceStartRemoteTx(minor);
261  }
262
263  return status;
264}
265
266/*
267 *  console_close
268 *
269 *  This routine closes a port that has been opened as console.
270 */
271rtems_device_driver console_close(
272  rtems_device_major_number major,
273  rtems_device_minor_number minor,
274  void                    * arg
275)
276{
277  rtems_libio_open_close_args_t *args = arg;
278  struct rtems_termios_tty      *current_tty;
279  console_tbl                   *cptr;
280
281  cptr  = Console_Port_Tbl[minor];
282
283  /* Get tty pointer from the Console_Port_Data */
284  current_tty = Console_Port_Data[minor].termios_data;
285
286  /* Get the tty refcount to determine if we need to do deviceStopRemoteTx.
287   * Stop only if it's the last one opened.
288   */
289  if ( (current_tty->refcount == 1) ) {
290    if ( (args->iop->flags&LIBIO_FLAGS_READ) &&
291          cptr->pDeviceFlow &&
292          cptr->pDeviceFlow->deviceStopRemoteTx) {
293      cptr->pDeviceFlow->deviceStopRemoteTx(minor);
294    }
295  }
296
297  return rtems_termios_close (arg);
298}
299
300/*
301 *  console_initialize
302 *
303 *  Routine called to initialize the console device driver.
304 */
305rtems_device_driver console_initialize(
306  rtems_device_major_number  major,
307  rtems_device_minor_number  minor_arg,
308  void                      *arg
309)
310{
311  rtems_status_code          status;
312  rtems_device_minor_number  minor;
313  console_tbl               *port;
314
315  /*
316   * If we have no devices which were registered earlier then we
317   * must still initialize pointers for Console_Port_Tbl and
318   * Console_Port_Data.
319   */
320  console_initialize_data();
321
322  /*
323   *  console_initialize has been invoked so it is now too late to
324   *  register devices.
325   */
326  console_initialized = true;
327
328  /*
329   *  Initialize the termio interface, our table of pointers to device
330   *  information structures, and determine if the user has explicitly
331   *  specified which device is to be used for the console.
332   */
333  rtems_termios_initialize();
334  bsp_console_select();
335
336  /*
337   *  Iterate over all of the console devices we know about
338   *  and initialize them.
339   */
340  for (minor=0 ; minor < Console_Port_Count ; minor++) {
341    /*
342     *  First perform the configuration dependent probe, then the
343     *  device dependent probe
344     */
345    port = Console_Port_Tbl[minor];
346
347    if ( (!port->deviceProbe || port->deviceProbe(minor)) &&
348         port->pDeviceFns->deviceProbe(minor)) {
349
350      if (port->sDeviceName != NULL) {
351        status = rtems_io_register_name( port->sDeviceName, major, minor );
352        if (status != RTEMS_SUCCESSFUL) {
353          bsp_fatal( BSP_FATAL_CONSOLE_REGISTER_DEV_0 );
354        }
355      }
356
357      if (minor == Console_Port_Minor) {
358        status = rtems_io_register_name( CONSOLE_DEVICE_NAME, major, minor );
359        if (status != RTEMS_SUCCESSFUL) {
360          bsp_fatal( BSP_FATAL_CONSOLE_REGISTER_DEV_1 );
361        }
362      }
363
364      /*
365       * Initialize the hardware device.
366       */
367      port->pDeviceFns->deviceInitialize(minor);
368
369    }
370  }
371
372  return RTEMS_SUCCESSFUL;
373}
Note: See TracBrowser for help on using the repository browser.