source: rtems/bsps/powerpc/ss555/console/console.c @ 90232bc

Last change on this file since 90232bc was d7d66d7, checked in by Sebastian Huber <sebastian.huber@…>, on Apr 19, 2018 at 4:28:01 AM

bsps: Move console drivers to bsps

This patch is a part of the BSP source reorganization.

Update #3285.

  • Property mode set to 100644
File size: 10.2 KB
Line 
1/*
2 *  console.c
3 *
4 *  This file contains the Intec SS555 termios serial I/O package.
5 *
6 *  The SCI channels are assigned as follows
7 *
8 *   Channel     Device      Minor
9 *    SCI1      /dev/tty0      0
10 *    SCI2      /dev/tty1      1
11 *
12 *  All ports support termios. The use of termios is recommended for real-time
13 *  applications. Termios provides buffering and input processing. When not
14 *  using termios, processing is limited to the substitution of LF for CR on
15 *  input, and the output of a CR following the output of a LF character.
16 *  Note that the terminal should not send CR/LF pairs when the return key
17 *  is pressed, and that output lines are terminated with LF/CR, not CR/LF
18 *  (although that would be easy to change).
19 *
20 *  I/O may be interrupt-driven (recommended for real-time applications) or
21 *  polled.
22 *
23 *  LIMITATIONS:
24 *
25 *  It is not possible to use different I/O modes on the different ports. The
26 *  exception is with printk. The printk port can use a different mode from
27 *  the other ports. If this is done, it is important not to open the printk
28 *  port from an RTEMS application.
29 *
30 *  Currently, the I/O modes are determined at build time. It would be much
31 *  better to have the mode selected at boot time based on parameters in
32 *  NVRAM.
33 *
34 *  Interrupt-driven I/O requires termios.
35 *
36 *  TESTS:
37 *
38 *  TO RUN THE TESTS, USE POLLED I/O WITHOUT TERMIOS SUPPORT. Some tests
39 *  play with the interrupt masks and turn off I/O. Those tests will hang
40 *  when interrupt-driven I/O is used. Other tests, such as cdtest, do I/O
41 *  from the static constructors before the console is open. This test
42 *  will not work with interrupt-driven I/O. Because of the buffering
43 *  performed in termios, test output may not be in sequence.The tests
44 *  should all be fixed to work with interrupt-driven I/O and to
45 *  produce output in the expected sequence. Obviously, the termios test
46 *  requires termios support in the driver.
47 *
48 *  Set CONSOLE_MINOR to the appropriate device minor number in the
49 *  config file. This allows the RTEMS application console to be different
50 *  from the GDB port.
51 *
52 *  This driver handles both available serial ports: it distinguishes
53 *  the sub-devices using minor device numbers. It is not possible to have
54 *  other protocols running on the other ports when this driver is used as
55 *  currently written.
56 *
57 *
58 *  SS555 port sponsored by Defence Research and Development Canada - Suffield
59 *  Copyright (C) 2004, Real-Time Systems Inc. (querbach@realtime.bc.ca)
60 *
61 *  Derived from c/src/lib/libbsp/powerpc/mbx8xx/console/console.c:
62 *
63 *  Based on code (alloc860.c in eth_comm port) by
64 *  Jay Monkman (jmonkman@frasca.com),
65 *  Copyright (C) 1998 by Frasca International, Inc.
66 *
67 *  Modifications by Darlene Stewart <Darlene.Stewart@iit.nrc.ca>
68 *  and Charles-Antoine Gauthier <charles.gauthier@iit.nrc.ca>.
69 *  Copyright (c) 2000, National Research Council of Canada
70 *
71 */
72#include <stdarg.h>
73#include <stdio.h>
74#include <termios.h>
75
76#include <rtems/console.h>
77#include <rtems/bspIo.h>
78#include <rtems/libio.h>
79#include <bsp.h>                /* Must be before libio.h */
80
81static void _BSP_output_char( char c );
82static rtems_status_code do_poll_read( rtems_device_major_number major, rtems_device_minor_number minor, void * arg);
83static rtems_status_code do_poll_write( rtems_device_major_number major, rtems_device_minor_number minor, void * arg);
84
85static void _BSP_null_char( char c ) {return;}
86
87BSP_output_char_function_type     BSP_output_char = _BSP_null_char;
88BSP_polling_getchar_function_type BSP_poll_char = NULL;
89
90/*
91 *  do_poll_read
92 *
93 *  Input characters through polled I/O. Returns as soon as a character has
94 *  been received. Otherwise, if we wait for the number of requested
95 *  characters, we could be here forever!
96 *
97 *  CR is converted to LF on input. The terminal should not send a CR/LF pair
98 *  when the return or enter key is pressed.
99 *
100 *  Input parameters:
101 *    major - ignored. Should be the major number for this driver.
102 *    minor - selected channel.
103 *    arg->buffer - where to put the received characters.
104 *    arg->count  - number of characters to receive before returning--Ignored.
105 *
106 *  Output parameters:
107 *    arg->bytes_moved - the number of characters read. Always 1.
108 *
109 *  Return value: RTEMS_SUCCESSFUL
110 *
111 *  CANNOT BE COMBINED WITH INTERRUPT DRIVEN I/O!
112 */
113static rtems_status_code do_poll_read(
114  rtems_device_major_number major,
115  rtems_device_minor_number minor,
116  void                    * arg
117)
118{
119  rtems_libio_rw_args_t *rw_args = arg;
120  int c;
121
122  while( (c = m5xx_uart_pollRead(minor)) == -1 );
123  rw_args->buffer[0] = (uint8_t)c;
124  if( rw_args->buffer[0] == '\r' )
125      rw_args->buffer[0] = '\n';
126  rw_args->bytes_moved = 1;
127
128  return RTEMS_SUCCESSFUL;
129}
130
131/*
132 *  do_poll_write
133 *
134 *  Output characters through polled I/O. Returns only once every character has
135 *  been sent.
136 *
137 *  CR is transmitted AFTER a LF on output.
138 *
139 *  Input parameters:
140 *    major - ignored. Should be the major number for this driver.
141 *    minor - selected channel
142 *    arg->buffer - where to get the characters to transmit.
143 *    arg->count  - the number of characters to transmit before returning.
144 *
145 *  Output parameters:
146 *    arg->bytes_moved - the number of characters read
147 *
148 *  Return value: RTEMS_SUCCESSFUL
149 *
150 *  CANNOT BE COMBINED WITH INTERRUPT DRIVEN I/O!
151 */
152static rtems_status_code do_poll_write(
153  rtems_device_major_number major,
154  rtems_device_minor_number minor,
155  void                    * arg
156)
157{
158  rtems_libio_rw_args_t *rw_args = arg;
159  uint32_t i;
160  char cr ='\r';
161
162  for( i = 0; i < rw_args->count; i++ ) {
163    m5xx_uart_pollWrite(minor, &(rw_args->buffer[i]), 1);
164    if ( rw_args->buffer[i] == '\n' )
165      m5xx_uart_pollWrite(minor, &cr, 1);
166  }
167  rw_args->bytes_moved = i;
168
169  return RTEMS_SUCCESSFUL;
170}
171
172/*
173 *  Print functions prototyped in bspIo.h
174 */
175
176static void _BSP_output_char( char c )
177{
178  char cr = '\r';
179
180  /*
181   *  Can't rely on console_initialize having been called before this
182   *  function is used, so it may fail.
183   */
184
185  m5xx_uart_pollWrite( PRINTK_MINOR, &c, 1 );
186  if( c == '\n' )
187    m5xx_uart_pollWrite( PRINTK_MINOR, &cr, 1 );
188}
189
190/*
191 ***************
192 * BOILERPLATE *
193 ***************
194 *
195 *  All these functions are prototyped in rtems/c/src/lib/include/console.h.
196 */
197
198/*
199 * Initialize and register the device
200 */
201rtems_device_driver console_initialize(
202  rtems_device_major_number major,
203  rtems_device_minor_number minor,
204  void *arg
205)
206{
207  rtems_status_code status;
208
209  /*
210   * Set up TERMIOS if needed
211   */
212  #if UARTS_USE_TERMIOS == 1
213    rtems_termios_initialize ();
214  #endif /* UARTS_USE_TERMIOS */
215
216  /*
217   * Do device-specific initialization
218   */
219  BSP_output_char = _BSP_output_char;
220
221  m5xx_uart_initialize(SCI1_MINOR);
222  status = rtems_io_register_name ("/dev/tty0", major, SCI1_MINOR);
223  if (status != RTEMS_SUCCESSFUL)
224    rtems_fatal_error_occurred (status);
225
226  m5xx_uart_initialize(SCI2_MINOR);
227  status = rtems_io_register_name ("/dev/tty1", major, SCI2_MINOR);
228  if (status != RTEMS_SUCCESSFUL)
229    rtems_fatal_error_occurred (status);
230
231  /* Now register the RTEMS console */
232  status = rtems_io_register_name ("/dev/console", major, CONSOLE_MINOR);
233  if (status != RTEMS_SUCCESSFUL)
234    rtems_fatal_error_occurred (status);
235
236  return RTEMS_SUCCESSFUL;
237}
238
239/*
240 * Open the device
241 */
242rtems_device_driver console_open(
243  rtems_device_major_number major,
244  rtems_device_minor_number minor,
245  void *arg
246)
247{
248  rtems_status_code sc;
249
250  if ( minor > NUM_PORTS - 1 )
251    return RTEMS_INVALID_NUMBER;
252
253  #if (UARTS_USE_TERMIOS == 1)
254  {
255    #if (UARTS_IO_MODE == 1)    /* RTEMS interrupt-driven I/O with termios */
256
257      static const rtems_termios_callbacks callbacks = {
258        m5xx_uart_firstOpen,            /* firstOpen */
259        m5xx_uart_lastClose,            /* lastClose */
260        NULL,                           /* pollRead */
261        m5xx_uart_write,                /* write */
262        m5xx_uart_setAttributes,        /* setAttributes */
263        NULL,                           /* stopRemoteTx */
264        NULL,                           /* startRemoteTx */
265        TERMIOS_IRQ_DRIVEN              /* outputUsesInterrupts */
266      };
267      sc = rtems_termios_open( major, minor, arg, &callbacks );
268
269    #else /* UARTS_IO_MODE != 1 */      /* RTEMS polled I/O with termios */
270
271      static const rtems_termios_callbacks callbacks = {
272        m5xx_uart_firstOpen,            /* firstOpen */
273        m5xx_uart_lastClose,            /* lastClose */
274        m5xx_uart_pollRead,             /* pollRead */
275        m5xx_uart_pollWrite,            /* write */
276        m5xx_uart_setAttributes,        /* setAttributes */
277        NULL,                           /* stopRemoteTx */
278        NULL,                           /* startRemoteTx */
279        TERMIOS_POLLED                  /* outputUsesInterrupts */
280      };
281      sc = rtems_termios_open( major, minor, arg, &callbacks );
282
283    #endif
284
285    return sc;
286  }
287
288  #else         /* no termios -- default to polled I/O */
289  {
290    sc = RTEMS_SUCCESSFUL;
291  }
292  #endif
293
294  return sc;
295}
296
297/*
298 * Close the device
299 */
300rtems_device_driver console_close(
301  rtems_device_major_number major,
302  rtems_device_minor_number minor,
303  void *arg
304)
305{
306  if ( minor > NUM_PORTS-1 )
307    return RTEMS_INVALID_NUMBER;
308
309  #if UARTS_USE_TERMIOS == 1
310    return rtems_termios_close( arg );
311  #else
312    return RTEMS_SUCCESSFUL;
313  #endif
314}
315
316/*
317 * Read from the device
318 */
319rtems_device_driver console_read(
320  rtems_device_major_number major,
321  rtems_device_minor_number minor,
322  void *arg
323)
324{
325  if ( minor > NUM_PORTS-1 )
326    return RTEMS_INVALID_NUMBER;
327
328  #if UARTS_USE_TERMIOS == 1
329    return rtems_termios_read( arg );
330  #else
331    return do_poll_read( major, minor, arg );
332  #endif
333}
334
335/*
336 * Write to the device
337 */
338rtems_device_driver console_write(
339  rtems_device_major_number major,
340  rtems_device_minor_number minor,
341  void *arg
342)
343{
344  if ( minor > NUM_PORTS-1 )
345    return RTEMS_INVALID_NUMBER;
346
347  #if UARTS_USE_TERMIOS == 1
348    return rtems_termios_write( arg );
349  #else
350    return do_poll_write( major, minor, arg );
351  #endif
352}
353
354/*
355 * Handle ioctl request.
356 */
357rtems_device_driver console_control(
358  rtems_device_major_number major,
359  rtems_device_minor_number minor,
360  void *arg
361)
362{
363  if ( minor > NUM_PORTS-1 )
364    return RTEMS_INVALID_NUMBER;
365
366  #if UARTS_USE_TERMIOS == 1
367    return rtems_termios_ioctl( arg );
368  #else
369    return RTEMS_SUCCESSFUL;
370  #endif
371}
Note: See TracBrowser for help on using the repository browser.