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

5
Last change on this file since c3c57b1 was c3c57b1, checked in by Joel Sherrill <joel@…>, on Mar 10, 2016 at 4:33:27 PM

pc386: Improve boot command arguments for console/printk device selection

This patch adds the "--printk=" boot command line argument to specify
the printk() device. It also enhances the "--console=" boot command
line argument to match any device configured in the console device
table. The arguments are parsed as early as possible so they take
effect early. Currently, this is immediately after PCI initialization.

  • 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_data
38 *
39 *  This method is used to initialize the table of pointers to the
40 *  serial port configuration structure entries.
41 */
42void console_initialize_data(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_data();
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_data();
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.