source: rtems/c/src/lib/libbsp/powerpc/ss555/console/console.c @ f05b2ac

4.104.114.84.95
Last change on this file since f05b2ac was f05b2ac, checked in by Ralf Corsepius <ralf.corsepius@…>, on 04/21/04 at 16:01:48

Remove duplicate white lines.

  • Property mode set to 100644
File size: 10.1 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 <bsp.h>                /* Must be before libio.h */
75#include <rtems/bspIo.h>
76#include <rtems/libio.h>
77#include <termios.h>
78
79static void _BSP_output_char( char c );
80static rtems_status_code do_poll_read( rtems_device_major_number major, rtems_device_minor_number minor, void * arg);
81static rtems_status_code do_poll_write( rtems_device_major_number major, rtems_device_minor_number minor, void * arg);
82
83static void _BSP_null_char( char c ) {return;}
84
85BSP_output_char_function_type BSP_output_char = _BSP_null_char;
86
87/*
88 *  do_poll_read
89 *
90 *  Input characters through polled I/O. Returns as soon as a character has
91 *  been received. Otherwise, if we wait for the number of requested
92 *  characters, we could be here forever!
93 *
94 *  CR is converted to LF on input. The terminal should not send a CR/LF pair
95 *  when the return or enter key is pressed.
96 *
97 *  Input parameters:
98 *    major - ignored. Should be the major number for this driver.
99 *    minor - selected channel.
100 *    arg->buffer - where to put the received characters.
101 *    arg->count  - number of characters to receive before returning--Ignored.
102 *
103 *  Output parameters:
104 *    arg->bytes_moved - the number of characters read. Always 1.
105 *
106 *  Return value: RTEMS_SUCCESSFUL
107 *
108 *  CANNOT BE COMBINED WITH INTERRUPT DRIVEN I/O!
109 */
110static rtems_status_code do_poll_read(
111  rtems_device_major_number major,
112  rtems_device_minor_number minor,
113  void                    * arg
114)
115{
116  rtems_libio_rw_args_t *rw_args = arg;
117  int c;
118
119  while( (c = m5xx_uart_pollRead(minor)) == -1 );
120  rw_args->buffer[0] = (unsigned8)c;
121  if( rw_args->buffer[0] == '\r' )
122      rw_args->buffer[0] = '\n';
123  rw_args->bytes_moved = 1;
124
125  return RTEMS_SUCCESSFUL;
126}
127
128/*
129 *  do_poll_write
130 *
131 *  Output characters through polled I/O. Returns only once every character has
132 *  been sent.
133 *
134 *  CR is transmitted AFTER a LF on output.
135 *
136 *  Input parameters:
137 *    major - ignored. Should be the major number for this driver.
138 *    minor - selected channel
139 *    arg->buffer - where to get the characters to transmit.
140 *    arg->count  - the number of characters to transmit before returning.
141 *
142 *  Output parameters:
143 *    arg->bytes_moved - the number of characters read
144 *
145 *  Return value: RTEMS_SUCCESSFUL
146 *
147 *  CANNOT BE COMBINED WITH INTERRUPT DRIVEN I/O!
148 */
149static rtems_status_code do_poll_write(
150  rtems_device_major_number major,
151  rtems_device_minor_number minor,
152  void                    * arg
153)
154{
155  rtems_libio_rw_args_t *rw_args = arg;
156  unsigned32 i;
157  char cr ='\r';
158
159  for( i = 0; i < rw_args->count; i++ ) {
160    m5xx_uart_pollWrite(minor, &(rw_args->buffer[i]), 1);
161    if ( rw_args->buffer[i] == '\n' )
162      m5xx_uart_pollWrite(minor, &cr, 1);
163  }
164  rw_args->bytes_moved = i;
165
166  return RTEMS_SUCCESSFUL;
167}
168
169/*
170 *  Print functions prototyped in bspIo.h
171 */
172
173static void _BSP_output_char( char c )
174{
175  char cr = '\r';
176
177  /*
178   *  Can't rely on console_initialize having been called before this
179   *  function is used, so it may fail.
180   */
181
182  m5xx_uart_pollWrite( PRINTK_MINOR, &c, 1 );
183  if( c == '\n' )
184    m5xx_uart_pollWrite( PRINTK_MINOR, &cr, 1 );
185}
186
187/*
188 ***************
189 * BOILERPLATE *
190 ***************
191 *
192 *  All these functions are prototyped in rtems/c/src/lib/include/console.h.
193 */
194
195/*
196 * Initialize and register the device
197 */
198rtems_device_driver console_initialize(
199  rtems_device_major_number major,
200  rtems_device_minor_number minor,
201  void *arg
202)
203{
204  rtems_status_code status;
205
206  /*
207   * Set up TERMIOS if needed
208   */
209  #if UARTS_USE_TERMIOS == 1
210    rtems_termios_initialize ();
211  #endif /* UARTS_USE_TERMIOS */
212
213  /*
214   * Do device-specific initialization
215   */
216  BSP_output_char = _BSP_output_char;
217
218  m5xx_uart_initialize(SCI1_MINOR);
219  status = rtems_io_register_name ("/dev/tty0", major, SCI1_MINOR);
220  if (status != RTEMS_SUCCESSFUL)
221    rtems_fatal_error_occurred (status);
222
223  m5xx_uart_initialize(SCI2_MINOR);
224  status = rtems_io_register_name ("/dev/tty1", major, SCI2_MINOR);
225  if (status != RTEMS_SUCCESSFUL)
226    rtems_fatal_error_occurred (status);
227
228  /* Now register the RTEMS console */
229  status = rtems_io_register_name ("/dev/console", major, CONSOLE_MINOR);
230  if (status != RTEMS_SUCCESSFUL)
231    rtems_fatal_error_occurred (status);
232
233  return RTEMS_SUCCESSFUL;
234}
235
236/*
237 * Open the device
238 */
239rtems_device_driver console_open(
240  rtems_device_major_number major,
241  rtems_device_minor_number minor,
242  void *arg
243)
244{
245  rtems_status_code sc;
246
247  if ( minor > NUM_PORTS - 1 )
248    return RTEMS_INVALID_NUMBER;
249
250  #if (UARTS_USE_TERMIOS == 1)
251  {
252    #if (UARTS_IO_MODE == 1)    /* RTEMS interrupt-driven I/O with termios */
253
254      static const rtems_termios_callbacks callbacks = {
255        m5xx_uart_firstOpen,            /* firstOpen */
256        m5xx_uart_lastClose,            /* lastClose */
257        NULL,                           /* pollRead */
258        m5xx_uart_write,                /* write */
259        m5xx_uart_setAttributes,        /* setAttributes */
260        NULL,                           /* stopRemoteTx */
261        NULL,                           /* startRemoteTx */
262        TERMIOS_IRQ_DRIVEN              /* outputUsesInterrupts */
263      };
264      sc = rtems_termios_open( major, minor, arg, &callbacks );
265
266    #else /* UARTS_IO_MODE != 1 */      /* RTEMS polled I/O with termios */
267
268      static const rtems_termios_callbacks callbacks = {
269        m5xx_uart_firstOpen,            /* firstOpen */
270        m5xx_uart_lastClose,            /* lastClose */
271        m5xx_uart_pollRead,             /* pollRead */
272        m5xx_uart_pollWrite,            /* write */
273        m5xx_uart_setAttributes,        /* setAttributes */
274        NULL,                           /* stopRemoteTx */
275        NULL,                           /* startRemoteTx */
276        TERMIOS_POLLED                  /* outputUsesInterrupts */
277      };
278      sc = rtems_termios_open( major, minor, arg, &callbacks );
279
280    #endif
281
282    return sc;
283  }
284
285  #else         /* no termios -- default to polled I/O */
286  {
287    sc = RTEMS_SUCCESSFUL;
288  }
289  #endif
290
291  return sc;
292}
293
294/*
295 * Close the device
296 */
297rtems_device_driver console_close(
298  rtems_device_major_number major,
299  rtems_device_minor_number minor,
300  void *arg
301)
302{
303  if ( minor > NUM_PORTS-1 )
304    return RTEMS_INVALID_NUMBER;
305
306  #if UARTS_USE_TERMIOS == 1
307    return rtems_termios_close( arg );
308  #else
309    return RTEMS_SUCCESSFUL;
310  #endif
311}
312
313/*
314 * Read from the device
315 */
316rtems_device_driver console_read(
317  rtems_device_major_number major,
318  rtems_device_minor_number minor,
319  void *arg
320)
321{
322  if ( minor > NUM_PORTS-1 )
323    return RTEMS_INVALID_NUMBER;
324
325  #if UARTS_USE_TERMIOS == 1
326    return rtems_termios_read( arg );
327  #else
328    return do_poll_read( major, minor, arg );
329  #endif
330}
331
332/*
333 * Write to the device
334 */
335rtems_device_driver console_write(
336  rtems_device_major_number major,
337  rtems_device_minor_number minor,
338  void *arg
339)
340{
341  if ( minor > NUM_PORTS-1 )
342    return RTEMS_INVALID_NUMBER;
343
344  #if UARTS_USE_TERMIOS == 1
345    return rtems_termios_write( arg );
346  #else
347    return do_poll_write( major, minor, arg );
348  #endif
349}
350
351/*
352 * Handle ioctl request.
353 */
354rtems_device_driver console_control(
355  rtems_device_major_number major,
356  rtems_device_minor_number minor,
357  void *arg
358)
359{
360  if ( minor > NUM_PORTS-1 )
361    return RTEMS_INVALID_NUMBER;
362
363  #if UARTS_USE_TERMIOS == 1
364    return rtems_termios_ioctl( arg );
365  #else
366    return RTEMS_SUCCESSFUL;
367  #endif
368}
Note: See TracBrowser for help on using the repository browser.