source: rtems/c/src/lib/libbsp/powerpc/mpc8260ads/console/console.c @ 00d8424e

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