source: rtems/c/src/lib/libbsp/shared/console.c @ 2e98d46

4.115
Last change on this file since 2e98d46 was 2e98d46, checked in by Ralf Corsepius <ralf.corsepius@…>, on 10/19/11 at 09:20:28

2011-10-19 Ralf Corsépius <ralf.corsepius@…>

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