source: rtems/c/src/lib/libbsp/shared/console.c @ 7c0273e

4.115
Last change on this file since 7c0273e was 7c0273e, checked in by Jennifer Averett <Jennifer.Averett@…>, on 11/18/11 at 20:08:15

2011-11-18 Jennifer Averett <Jennifer.Averett@…>

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