source: rtems/c/src/lib/libbsp/shared/console.c @ 90d8567

Last change on this file since 90d8567 was c499856, checked in by Chris Johns <chrisj@…>, on Mar 20, 2014 at 9:10:47 PM

Change all references of rtems.com to rtems.org.

  • Property mode set to 100644
File size: 8.2 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.
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_initialize_pointers
38 *
39 *  This method is used to initialize the table of pointers to the
40 *  serial port configuration structure entries.
41 */
42static void console_initialize_pointers(void)
43{
44  int i;
45
46  if ( Console_Port_Tbl )
47    return;
48
49  Console_Port_Count = Console_Configuration_Count;
50  Console_Port_Tbl   = malloc( Console_Port_Count * sizeof( console_tbl * ) );
51  if (Console_Port_Tbl == NULL)
52    bsp_fatal( BSP_FATAL_CONSOLE_NO_MEMORY_0 );
53
54  for (i=0 ; i < Console_Port_Count ; i++)
55    Console_Port_Tbl[i] = &Console_Configuration_Ports[i];
56}
57
58/*
59 *  console_register_devices
60 *
61 *  This method is used to add dynamically discovered devices to the
62 *  set of serial ports supported.
63 */
64void console_register_devices(
65  console_tbl *new_ports,
66  size_t       number_of_ports
67)
68{
69  int  old_number_of_ports;
70  int  i;
71
72  console_initialize_pointers();
73
74  /*
75   *  console_initialize has been invoked so it is now too late to
76   *  register devices.
77   */
78  if ( console_initialized ) {
79    bsp_fatal( BSP_FATAL_CONSOLE_MULTI_INIT );
80  }
81
82  /*
83   *  Allocate memory for the console port extension
84   */
85  old_number_of_ports = Console_Port_Count;
86  Console_Port_Count += number_of_ports;
87  Console_Port_Tbl = realloc(
88    Console_Port_Tbl,
89    Console_Port_Count * sizeof( console_tbl * )
90  );
91  if ( Console_Port_Tbl == NULL ) {
92    bsp_fatal( BSP_FATAL_CONSOLE_NO_MEMORY_1 );
93  }
94
95  Console_Port_Data  = calloc( Console_Port_Count, sizeof( console_data ) );
96  if ( Console_Port_Data == NULL ) {
97    bsp_fatal( BSP_FATAL_CONSOLE_NO_MEMORY_2 );
98  }
99
100  /*
101   *  Now add the new devices at the end.
102   */
103
104  for (i=0 ; i < number_of_ports ; i++) {
105    Console_Port_Tbl[old_number_of_ports + i] = &new_ports[i];
106  }
107}
108
109/*
110 *  console_open
111 *
112 *  open a port as a termios console.
113 */
114rtems_device_driver console_open(
115  rtems_device_major_number major,
116  rtems_device_minor_number minor,
117  void                    * arg
118)
119{
120  rtems_status_code              status;
121  rtems_libio_open_close_args_t *args = arg;
122  rtems_libio_ioctl_args_t       IoctlArgs;
123  struct termios                 Termios;
124  rtems_termios_callbacks        Callbacks;
125  console_tbl                   *cptr;
126  struct rtems_termios_tty      *current_tty;
127
128  /*
129   * Verify the port number is valid.
130   */
131  if ( minor > Console_Port_Count ) {
132    return RTEMS_INVALID_NUMBER;
133  }
134
135  /*
136   * Open the port as a termios console driver.
137   */
138
139  cptr = Console_Port_Tbl[minor];
140  Callbacks.firstOpen            = cptr->pDeviceFns->deviceFirstOpen;
141  Callbacks.lastClose            = cptr->pDeviceFns->deviceLastClose;
142  Callbacks.pollRead             = cptr->pDeviceFns->deviceRead;
143  Callbacks.write                = cptr->pDeviceFns->deviceWrite;
144  Callbacks.setAttributes        = cptr->pDeviceFns->deviceSetAttributes;
145  if (cptr->pDeviceFlow != NULL) {
146    Callbacks.stopRemoteTx  = cptr->pDeviceFlow->deviceStopRemoteTx;
147    Callbacks.startRemoteTx = cptr->pDeviceFlow->deviceStartRemoteTx;
148  } else {
149    Callbacks.stopRemoteTx  = NULL;
150    Callbacks.startRemoteTx = NULL;
151  }
152  Callbacks.outputUsesInterrupts = cptr->pDeviceFns->deviceOutputUsesInterrupts;
153
154  /* XXX what about
155   *        Console_Port_Tbl[minor].ulMargin,
156   *        Console_Port_Tbl[minor].ulHysteresis);
157   */
158
159  status = rtems_termios_open( major, minor, arg, &Callbacks );
160  Console_Port_Data[minor].termios_data = args->iop->data1;
161
162  /* Get tty pointur from the Console_Port_Data */
163  current_tty = Console_Port_Data[minor].termios_data;
164
165  if ( (current_tty->refcount == 1) ) {
166
167    /*
168     *  If this BSP has a preferred default rate, then use that.
169     */
170    #if defined(BSP_DEFAULT_BAUD_RATE)
171      rtems_termios_set_initial_baud( current_tty, BSP_DEFAULT_BAUD_RATE );
172    #endif
173
174    /*
175     * If it's the first open, modified, if need, the port parameters
176     */
177    if ( minor != Console_Port_Minor ) {
178      /*
179       * If this is not the console we do not want ECHO and so forth
180       */
181      IoctlArgs.iop     = args->iop;
182      IoctlArgs.command = RTEMS_IO_GET_ATTRIBUTES;
183      IoctlArgs.buffer  = &Termios;
184      rtems_termios_ioctl( &IoctlArgs );
185
186      Termios.c_lflag   = ICANON;
187      IoctlArgs.command = RTEMS_IO_SET_ATTRIBUTES;
188      rtems_termios_ioctl( &IoctlArgs );
189    }
190  }
191
192  if ( (args->iop->flags&LIBIO_FLAGS_READ) &&
193      cptr->pDeviceFlow &&
194      cptr->pDeviceFlow->deviceStartRemoteTx) {
195    cptr->pDeviceFlow->deviceStartRemoteTx(minor);
196  }
197
198  return status;
199}
200
201/*
202 *  console_close
203 *
204 *  This routine closes a port that has been opened as console.
205 */
206rtems_device_driver console_close(
207  rtems_device_major_number major,
208  rtems_device_minor_number minor,
209  void                    * arg
210)
211{
212  rtems_libio_open_close_args_t *args = arg;
213  struct rtems_termios_tty      *current_tty;
214  console_tbl                   *cptr;
215
216  cptr  = Console_Port_Tbl[minor];
217
218  /* Get tty pointer from the Console_Port_Data */
219  current_tty = Console_Port_Data[minor].termios_data;
220
221  /* Get the tty refcount to determine if we need to do deviceStopRemoteTx.
222   * Stop only if it's the last one opened.
223   */
224  if ( (current_tty->refcount == 1) ) {
225    if ( (args->iop->flags&LIBIO_FLAGS_READ) &&
226          cptr->pDeviceFlow &&
227          cptr->pDeviceFlow->deviceStopRemoteTx) {
228      cptr->pDeviceFlow->deviceStopRemoteTx(minor);
229    }
230  }
231
232  return rtems_termios_close (arg);
233}
234
235/*
236 *  console_initialize
237 *
238 *  Routine called to initialize the console device driver.
239 */
240rtems_device_driver console_initialize(
241  rtems_device_major_number  major,
242  rtems_device_minor_number  minor_arg,
243  void                      *arg
244)
245{
246  rtems_status_code          status;
247  rtems_device_minor_number  minor;
248  console_tbl               *port;
249
250  /*
251   * If we have no devices which were registered earlier then we
252   * must still initialize pointers and set Console_Port_Data.
253   */
254  if ( ! Console_Port_Tbl ) {
255    console_initialize_pointers();
256    Console_Port_Data  = calloc( Console_Port_Count, sizeof( console_data ) );
257    if ( Console_Port_Data == NULL ) {
258      bsp_fatal( BSP_FATAL_CONSOLE_NO_MEMORY_3 );
259    }
260  }
261
262  /*
263   *  console_initialize has been invoked so it is now too late to
264   *  register devices.
265   */
266  console_initialized = true;
267
268  /*
269   *  Initialize the termio interface, our table of pointers to device
270   *  information structures, and determine if the user has explicitly
271   *  specified which device is to be used for the console.
272   */
273  rtems_termios_initialize();
274  bsp_console_select();
275
276  /*
277   *  Iterate over all of the console devices we know about
278   *  and initialize them.
279   */
280  for (minor=0 ; minor < Console_Port_Count ; minor++) {
281    /*
282     *  First perform the configuration dependent probe, then the
283     *  device dependent probe
284     */
285    port = Console_Port_Tbl[minor];
286
287    if ( (!port->deviceProbe || port->deviceProbe(minor)) &&
288         port->pDeviceFns->deviceProbe(minor)) {
289
290      if (port->sDeviceName != NULL) {
291        status = rtems_io_register_name( port->sDeviceName, major, minor );
292        if (status != RTEMS_SUCCESSFUL) {
293          bsp_fatal( BSP_FATAL_CONSOLE_REGISTER_DEV_0 );
294        }
295      }
296
297      if (minor == Console_Port_Minor) {
298        status = rtems_io_register_name( CONSOLE_DEVICE_NAME, major, minor );
299        if (status != RTEMS_SUCCESSFUL) {
300          bsp_fatal( BSP_FATAL_CONSOLE_REGISTER_DEV_1 );
301        }
302      }
303
304      /*
305       * Initialize the hardware device.
306       */
307      port->pDeviceFns->deviceInitialize(minor);
308
309    }
310  }
311
312  return RTEMS_SUCCESSFUL;
313}
Note: See TracBrowser for help on using the repository browser.