source: rtems/c/src/lib/libbsp/powerpc/mpc8260ads/console/console.c @ 1bc0ad2

Last change on this file since 1bc0ad2 was 1bc0ad2, checked in by Sebastian Huber <sebastian.huber@…>, on Sep 8, 2017 at 8:38:46 AM

Simplify and unify BSP_output_char

The BSP_output_char should output a char and not mingle with high level
processing, e.g. '\n' to '\r\n' translation. Move this translation to
rtems_putc(). Remove it from all the BSP_output_char implementations.

Close #3122.

  • Property mode set to 100644
File size: 12.8 KB
Line 
1/*
2 *  This file contains the MBX8xx termios serial I/O package.
3 *  Only asynchronous I/O is supported.
4 *
5 *  The SCCs and SMCs are assigned as follows
6 *
7 *   Channel     Device      Minor   Note
8 *    SMC1      /dev/tty0      0
9 *    SMC2      /dev/tty1      1
10 *    SCC1                     2     N/A. Hardwired as ethernet port
11 *    SCC2      /dev/tty2      3
12 *    SCC3      /dev/tty3      4
13 *    SCC4      /dev/tty4      5
14 *
15 * The SCCs and SMCs on the eval board are assigned as follows
16 *
17 *   Channel     Device      Minor   Termios
18 *    SMC1      /dev/tty3      4       no
19 *    SMC2      /dev/tty4      5       no
20 *    SCC1      /dev/tty0      0       no
21 *    SCC2      /dev/console   1       yes
22 *    SCC3      /dev/tty1      2       no       * USED FOR NETWORK I/F
23 *    SCC4      /dev/tty2      3       no       * USED FOR NETWORK I/F
24 *
25 *  All ports support termios. The use of termios is recommended for real-time
26 *  applications. Termios provides buffering and input processing. When not
27 *  using termios, processing is limited to the substitution of LF for CR on
28 *  input, and the output of a CR following the output of a LF character.
29 *  Note that the terminal should not send CR/LF pairs when the return key
30 *  is pressed, and that output lines are terminated with LF/CR, not CR/LF
31 *  (although that would be easy to change).
32 *
33 *  I/O may be interrupt-driven (recommended for real-time applications) or
34 *  polled. Polled I/O may be performed by this device driver entirely, or
35 *  in part by EPPCBug. With EPPCBug 1.1, polled I/O is limited to the
36 *  EPPCBug debug console. This is a limitation of the firmware. Later
37 *  firmware may be able to do I/O through any port. This code assumes
38 *  that the EPPCBug console is the default: SMC1. If the console and
39 *  printk ports are set to anything else with EPPCBug polled I/O, the
40 *  system will hang. Only port SMC1 is usable with EPPCBug polled I/O.
41 *
42 *  LIMITATIONS:
43 *
44 *  It is not possible to use different I/O modes on the different ports. The
45 *  exception is with printk. The printk port can use a different mode from
46 *  the other ports. If this is done, it is important not to open the printk
47 *  port from an RTEMS application.
48 *
49 *  Currently, the I/O modes are determined at build time. It would be much
50 *  better to have the mode selected at boot time based on parameters in
51 *  NVRAM.
52 *
53 *  Interrupt-driven I/O requires termios.
54 *
55 *  TESTS:
56 *
57 *  TO RUN THE TESTS, USE POLLED I/O WITHOUT TERMIOS SUPPORT. Some tests
58 *  play with the interrupt masks and turn off I/O. Those tests will hang
59 *  when interrupt-driven I/O is used. Other tests, such as cdtest, do I/O
60 *  from the static constructors before the console is open. This test
61 *  will not work with interrupt-driven I/O. Because of the buffering
62 *  performed in termios, test output may not be in sequence.The tests
63 *  should all be fixed to work with interrupt-driven I/O and to
64 *  produce output in the expected sequence. Obviously, the termios test
65 *  requires termios support in the driver.
66 *
67 *  Set CONSOLE_MINOR to the appropriate device minor number in the
68 *  config file. This allows the RTEMS application console to be different
69 *  from the EPPBug debug console or the GDB port.
70 *
71 *  This driver handles all five available serial ports: it distinguishes
72 *  the sub-devices using minor device numbers. It is not possible to have
73 *  other protocols running on the other ports when this driver is used as
74 *  currently written.
75 */
76
77/*
78 *  Based on code (alloc860.c in eth_comm port) by
79 *  Jay Monkman (jmonkman@frasca.com),
80 *  Copyright (C) 1998 by Frasca International, Inc.
81 *
82 *  Modifications by Darlene Stewart <Darlene.Stewart@iit.nrc.ca>
83 *  and Charles-Antoine Gauthier <charles.gauthier@iit.nrc.ca>.
84 *  Copyright (c) 2000, National Research Council of Canada
85 *
86 *  Modifications by Andy Dachs <iwe@fsmal.net> for MPC8260
87 *  support.
88 */
89#include <stdarg.h>
90#include <stdio.h>
91#include <termios.h>
92
93#include <rtems/console.h>
94#include <rtems/bspIo.h>
95#include <rtems/libio.h>
96#include <bsp.h>
97
98static void _BSP_output_char( char c );
99static rtems_status_code do_poll_read( rtems_device_major_number major, rtems_device_minor_number minor, void * arg);
100static rtems_status_code do_poll_write( rtems_device_major_number major, rtems_device_minor_number minor, void * arg);
101
102BSP_output_char_function_type     BSP_output_char = _BSP_output_char;
103BSP_polling_getchar_function_type BSP_poll_char = NULL;
104
105/*
106 *  do_poll_read
107 *
108 *  Input characters through polled I/O. Returns has soon as a character has
109 *  been received. Otherwise, if we wait for the number of requested characters,
110 *  we could be here forever!
111 *
112 *  CR is converted to LF on input. The terminal should not send a CR/LF pair
113 *  when the return or enter key is pressed.
114 *
115 *  Input parameters:
116 *    major - ignored. Should be the major number for this driver.
117 *    minor - selected channel.
118 *    arg->buffer - where to put the received characters.
119 *    arg->count  - number of characters to receive before returning--Ignored.
120 *
121 *  Output parameters:
122 *    arg->bytes_moved - the number of characters read. Always 1.
123 *
124 *  Return value: RTEMS_SUCCESSFUL
125 *
126 *  CANNOT BE COMBINED WITH INTERRUPT DRIVEN I/O!
127 */
128static rtems_status_code do_poll_read(
129  rtems_device_major_number major,
130  rtems_device_minor_number minor,
131  void                    * arg
132)
133{
134  rtems_libio_rw_args_t *rw_args = arg;
135  int c;
136
137#define BSP_READ  m8xx_uart_pollRead
138
139  while( (c = BSP_READ(minor)) == -1 );
140  rw_args->buffer[0] = (uint8_t)c;
141  if( rw_args->buffer[0] == '\r' )
142      rw_args->buffer[0] = '\n';
143  rw_args->bytes_moved = 1;
144  return RTEMS_SUCCESSFUL;
145}
146
147/*
148 *  do_poll_write
149 *
150 *  Output characters through polled I/O. Returns only once every character has
151 *  been sent.
152 *
153 *  CR is transmitted AFTER a LF on output.
154 *
155 *  Input parameters:
156 *    major - ignored. Should be the major number for this driver.
157 *    minor - selected channel
158 *    arg->buffer - where to get the characters to transmit.
159 *    arg->count  - the number of characters to transmit before returning.
160 *
161 *  Output parameters:
162 *    arg->bytes_moved - the number of characters read
163 *
164 *  Return value: RTEMS_SUCCESSFUL
165 *
166 *  CANNOT BE COMBINED WITH INTERRUPT DRIVEN I/O!
167 */
168static rtems_status_code do_poll_write(
169  rtems_device_major_number major,
170  rtems_device_minor_number minor,
171  void                    * arg
172)
173{
174  rtems_libio_rw_args_t *rw_args = arg;
175  uint32_t   i;
176  char cr ='\r';
177
178#define BSP_WRITE m8xx_uart_pollWrite
179
180  for( i = 0; i < rw_args->count; i++ ) {
181    BSP_WRITE(minor, &(rw_args->buffer[i]), 1);
182    if ( rw_args->buffer[i] == '\n' )
183      BSP_WRITE(minor, &cr, 1);
184  }
185  rw_args->bytes_moved = i;
186  return RTEMS_SUCCESSFUL;
187
188}
189
190/*
191 *  Print functions prototyped in bspIo.h
192 */
193
194static void _BSP_output_char( char c )
195{
196  /*
197   *  Can't rely on console_initialize having been called before this function
198   *  is used, so it may fail unless output is done through EPPC-Bug.
199   */
200#define PRINTK_WRITE m8xx_uart_pollWrite
201
202  PRINTK_WRITE( PRINTK_MINOR, &c, 1 );
203}
204
205/*
206 ***************
207 * BOILERPLATE *
208 ***************
209 *
210 *  All these functions are prototyped in rtems/c/src/lib/include/console.h.
211 */
212
213/*
214 * Initialize and register the device
215 */
216rtems_device_driver console_initialize(
217  rtems_device_major_number major,
218  rtems_device_minor_number minor,
219  void *arg
220)
221{
222  rtems_status_code status;
223  rtems_device_minor_number console_minor;
224
225  /*
226   * Set up TERMIOS if needed
227   */
228
229    console_minor = CONSOLE_MINOR;
230
231#if UARTS_USE_TERMIOS == 1
232
233    rtems_termios_initialize ();
234#else
235    rtems_termios_initialize ();
236#endif /* UARTS_USE_TERMIOS */
237
238  /*
239   *  Do common initialization.
240   */
241  m8xx_uart_initialize();
242
243  /*
244   * Do device-specific initialization
245   */
246#if 0
247  m8xx_uart_smc_initialize(SMC1_MINOR); /* /dev/tty4 */
248  m8xx_uart_smc_initialize(SMC2_MINOR); /* /dev/tty5 */
249#endif
250
251  m8xx_uart_scc_initialize(SCC1_MINOR); /* /dev/tty0    */
252  m8xx_uart_scc_initialize(SCC2_MINOR); /* /dev/tty1    */
253
254#if 0  /* used as network connections */
255  m8xx_uart_scc_initialize(SCC3_MINOR); /* /dev/tty2    */
256  m8xx_uart_scc_initialize(SCC4_MINOR); /* /dev/tty3    */
257#endif
258
259  /*
260   * Set up interrupts
261   */
262  m8xx_uart_interrupts_initialize();
263
264  status = rtems_io_register_name ("/dev/tty0", major, SCC1_MINOR);
265  if (status != RTEMS_SUCCESSFUL)
266    rtems_fatal_error_occurred (status);
267  chmod("/dev/tty0",0660);
268  chown("/dev/tty0",2,0);
269
270  status = rtems_io_register_name ("/dev/tty1", major, SCC2_MINOR);
271  if (status != RTEMS_SUCCESSFUL)
272    rtems_fatal_error_occurred (status);
273  chmod("/dev/tty1",0660);
274  chown("/dev/tty1",2,0);
275
276#if 0
277  status = rtems_io_register_name ("/dev/tty2", major, SCC3_MINOR);
278  if (status != RTEMS_SUCCESSFUL)
279    rtems_fatal_error_occurred (status);
280
281  status = rtems_io_register_name ("/dev/tty3", major, SCC4_MINOR);
282  if (status != RTEMS_SUCCESSFUL)
283    rtems_fatal_error_occurred (status);
284
285  status = rtems_io_register_name ("/dev/tty4", major, SMC1_MINOR);
286  if (status != RTEMS_SUCCESSFUL)
287    rtems_fatal_error_occurred (status);
288
289  status = rtems_io_register_name ("/dev/tty5", major, SMC2_MINOR);
290  if (status != RTEMS_SUCCESSFUL)
291    rtems_fatal_error_occurred (status);
292#endif
293  /* Now register the RTEMS console */
294  status = rtems_io_register_name ("/dev/console", major, console_minor);
295  if (status != RTEMS_SUCCESSFUL)
296    rtems_fatal_error_occurred (status);
297  chmod("/dev/console",0666);
298  chown("/dev/console",2,0);
299
300  return RTEMS_SUCCESSFUL;
301}
302
303/*
304 * Open the device
305 */
306rtems_device_driver console_open(
307  rtems_device_major_number major,
308  rtems_device_minor_number minor,
309  void *arg
310)
311{
312#if UARTS_IO_MODE == 1  /* RTEMS interrupt-driven I/O with termios */
313  /* Used to track termios private data for callbacks */
314  extern struct rtems_termios_tty *ttyp[];
315  rtems_libio_open_close_args_t *args = arg;
316
317  static const rtems_termios_callbacks intrCallbacks = {
318    NULL,                               /* firstOpen */
319    NULL,                               /* lastClose */
320    NULL,                         /* pollRead */
321    m8xx_uart_write,                  /* write */
322    m8xx_uart_setAttributes,            /* setAttributes */
323    NULL,                               /* stopRemoteTx */
324    NULL,                               /* startRemoteTx */
325    1                                   /* outputUsesInterrupts */
326  };
327#else
328#if (UARTS_USE_TERMIOS == 1) && (UARTS_IO_MODE != 1)
329  static const rtems_termios_callbacks pollCallbacks = {
330    NULL,                               /* firstOpen */
331    NULL,                               /* lastClose */
332    m8xx_uart_pollRead,           /* pollRead */
333    m8xx_uart_pollWrite,          /* write */
334    m8xx_uart_setAttributes,      /* setAttributes */
335    NULL,                               /* stopRemoteTx */
336    NULL,                               /* startRemoteTx */
337    0                                   /* outputUsesInterrupts */
338  };
339#endif
340
341#endif
342
343  rtems_status_code sc;
344
345  if ( minor > NUM_PORTS-1 )
346    return RTEMS_INVALID_NUMBER;
347
348#if UARTS_USE_TERMIOS == 1
349
350#if UARTS_IO_MODE == 1  /* RTEMS interrupt-driven I/O with termios */
351  sc = rtems_termios_open( major, minor, arg, &intrCallbacks );
352  ttyp[minor] = args->iop->data1;        /* Keep cookie returned by termios_open */
353#else                     /* RTEMS polled I/O with termios */
354  sc = rtems_termios_open( major, minor, arg, &pollCallbacks );
355#endif
356
357#else /* UARTS_USE_TERMIOS != 1 */
358  /* no termios -- default to polled I/O */
359  sc = RTEMS_SUCCESSFUL;
360#endif /* UARTS_USE_TERMIOS != 1 */
361
362  return sc;
363
364}
365
366/*
367 * Close the device
368 */
369rtems_device_driver console_close(
370  rtems_device_major_number major,
371  rtems_device_minor_number minor,
372  void *arg
373)
374{
375  if ( minor > NUM_PORTS-1 )
376    return RTEMS_INVALID_NUMBER;
377
378#if UARTS_USE_TERMIOS == 1
379  return rtems_termios_close( arg );
380#else
381  return RTEMS_SUCCESSFUL;
382#endif
383
384}
385
386/*
387 * Read from the device
388 */
389rtems_device_driver console_read(
390  rtems_device_major_number major,
391  rtems_device_minor_number minor,
392  void *arg
393)
394{
395  if ( minor > NUM_PORTS-1 )
396    return RTEMS_INVALID_NUMBER;
397
398#if UARTS_USE_TERMIOS == 1
399  return rtems_termios_read( arg );
400#else
401  return do_poll_read( major, minor, arg );
402#endif
403
404}
405
406/*
407 * Write to the device
408 */
409rtems_device_driver console_write(
410  rtems_device_major_number major,
411  rtems_device_minor_number minor,
412  void *arg
413)
414{
415  if ( minor > NUM_PORTS-1 )
416    return RTEMS_INVALID_NUMBER;
417
418#if UARTS_USE_TERMIOS == 1
419  return rtems_termios_write( arg );
420#else
421    /* no termios -- default to polled */
422  return do_poll_write( major, minor, arg );
423#endif
424
425}
426
427/*
428 * Handle ioctl request.
429 */
430rtems_device_driver console_control(
431  rtems_device_major_number major,
432  rtems_device_minor_number minor,
433  void *arg
434)
435{
436  if ( minor > NUM_PORTS-1 )
437    return RTEMS_INVALID_NUMBER;
438
439#if UARTS_USE_TERMIOS == 1
440  return rtems_termios_ioctl( arg );
441#else
442  return RTEMS_SUCCESSFUL;
443#endif
444
445}
446
447/*
448 *  Support routine for console-generic
449 */
450int mbx8xx_console_get_configuration(void)
451{
452#if UARTS_IO_MODE == 1
453  return 0x02;
454#else
455  return 0;
456#endif
457
458}
Note: See TracBrowser for help on using the repository browser.