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

5
Last change on this file since 22bbb9f1 was 22bbb9f1, checked in by Joel Sherrill <joel@…>, on 03/09/16 at 18:48:39

pc386: Add --disable-com1-com4 boot argument

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