source: rtems/c/src/lib/libbsp/powerpc/mbx8xx/console/console.c @ 310a2ec

4.104.114.84.95
Last change on this file since 310a2ec was 8ef3818, checked in by Joel Sherrill <joel.sherrill@…>, on 06/12/00 at 19:57:02

Patch from John Cotton <john.cotton@…>, Charles-Antoine Gauthier
<charles.gauthier@…>, and Darlene A. Stewart
<Darlene.Stewart@…> to add support for a number of very
significant things:

+ BSPs for many variations on the Motorola MBX8xx board series
+ Cache Manager including initial support for m68040

and PowerPC

+ Rework of mpc8xx libcpu code so all mpc8xx CPUs now use

same code base.

+ Rework of eth_comm BSP to utiltize above.

John reports this works on the 821 and 860

  • Property mode set to 100644
File size: 12.3 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. All I/O is interrupt-driven, unless EPPCBug
18 *  is used to do the I/O. To use EPPCBug, define the EPPCBUG_SMC1
19 *  manifest constant in the configuration file (mbx8xx.cfg). EPPCBug I/O
20 *  is currently limited to the EPPCBug debug console. This is a limitation
21 *  of firmware revision 1.1. Later firmware should be able to do I/O
22 *  through any port.This code assumes that the EPPCBug console is the
23 *  default: SMC1.
24 *
25 *  TO RUN THE TESTS, USE POLLED I/O THROUGH EPPCBUG. Some tests play with
26 *  the interrupt masks and turn off I/O. Those tests will hang with when
27 *  interrupt-driven I/O is used.
28 * 
29 *  Set CONSOLE_MINOR to the appropriate device minor number in the
30 *  config file. This allows the RTEMS application console to be different
31 *  from the EPPBug debug console or the GDB stup I/O port.
32 *
33 *  This driver handles all five available serial ports: it distinguishes
34 *  the sub-devices using minor device numbers. It is not possible to have
35 *  other protocols running on the other ports when this driver is used as
36 *  currently written.
37 * 
38 *  Based on code (alloc860.c in eth_comm port) by
39 *  Jay Monkman (jmonkman@frasca.com),
40 *  Copyright (C) 1998 by Frasca International, Inc.
41 *
42 *  Modifications by Darlene Stewart <Darlene.Stewart@iit.nrc.ca>
43 *  and Charles-Antoine Gauthier <charles.gauthier@iit.nrc.ca>.
44 *  Copyright (c) 1999, National Research Council of Canada
45 *
46 */
47#include <stdarg.h>
48#include <stdio.h>
49#include <bsp.h>                /* Must be before libio.h */
50#include <rtems/libio.h>
51#include <termios.h>
52
53static int _EPPCBug_pollRead( int minor );
54static int _EPPCBug_pollWrite( int minor, const char *buf, int len );
55
56
57/*
58 * _EPPCBug_pollRead
59 *
60 *  Read a character from the EPPCBug console, and return it. Return -1
61 *  if there is no character in the input FIFO.
62 *
63 *  Input parameters:
64 *    minor - selected channel
65 *
66 *  Output parameters:  NONE
67 *
68 *  Return value: char returned as positive signed int
69 *                -1 if no character is present in the input FIFO.
70 */
71int _EPPCBug_pollRead(
72  int minor
73)
74{
75  extern volatile m8xx_t m8xx;
76
77  char c;
78  volatile int simask;          /* We must read and write m8xx.simask */
79  int retval;
80  ISR_Level level;
81 
82  struct {
83    int clun;
84    int dlun;
85    char * inbuf;
86    int nbytes_requested;
87    int reserved;
88  } volatile input_params;
89 
90  struct {
91    int status;
92    union {
93      struct {
94        int input_char_available;
95        int output_possible;
96        int break_detected;
97        int modem_status;
98      } stat;
99      struct {
100        int nbytes_received;
101      } read;
102    } u;
103  } volatile output_params;
104
105  retval = -1;
106
107  /* Input through EPPCBug console  */
108  input_params.clun = 0;
109  input_params.dlun = 0;
110  input_params.reserved = 0;
111 
112  _ISR_Disable( level );
113  simask = m8xx.simask;
114
115  /* Check for a char in the input FIFO using .CIO_STAT */
116  asm volatile( "li 10,0x202
117                 mr 3, %0
118                 mr 4, %1
119                 sc"
120    :: "g" (&input_params), "g" (&output_params) : "3", "4", "10" );
121
122  if ( (output_params.status == 0) && output_params.u.stat.input_char_available) {
123 
124    /* Read the char and return it */
125    input_params.inbuf = &c;
126    input_params.nbytes_requested = 1;
127 
128    asm volatile( "li     10,0x200     /* Code for .CIO_READ */
129                   mr    3, %0         /* Address of input_params */
130                   mr    4, %1         /* Address of output_params */
131                   sc"             /* Call EPPCBUG */
132      :: "g" (&input_params), "g" (&output_params) : "3", "4", "10" );
133
134    if ( (output_params.status == 0) && output_params.u.read.nbytes_received)
135      retval = (int)c;
136  }
137 
138  m8xx.simask = simask;
139  _ISR_Enable( level );
140  return retval;
141}
142
143
144/*
145 * _EPPCBug_pollWrite
146 *
147 *  Output buffer through EPPCBug. Returns only once every character has been
148 *  sent (polled output).
149 *
150 *  Input parameters:
151 *    minor - selected channel
152 *    buf - output buffer
153 *    len - number of chars to output
154 *
155 *  Output parameters:  NONE
156 *
157 *  Return value: IGNORED
158 */
159int _EPPCBug_pollWrite(
160  int minor,
161  const char *buf,
162  int len
163)
164{
165  extern volatile m8xx_t m8xx;
166
167  volatile int simask;
168  int i, retval;
169  ISR_Level level;
170 
171  struct {
172    int clun;
173    int dlun;
174    const char * outbuf;
175    int nbytes_to_output;
176    int reserved;
177  } volatile input_params;
178 
179  struct {
180    int status;
181    union {
182      struct {
183        int input_char_available;
184        int output_possible;
185        int break_detected;
186        int modem_status;
187      } stat;
188      struct {
189        int nbytes_sent;
190      } write;
191    } u;
192  } volatile output_params;
193
194  retval = -1;
195
196  /* Output through EPPCBug console  */
197  input_params.clun = 0;
198  input_params.dlun = 0;
199  input_params.reserved = 0;
200
201  i = 0;
202
203  _ISR_Disable( level );
204  simask = m8xx.simask;
205
206  while (i < len) {
207    /* Wait for space in the output buffer */
208    do {
209      /* Check for space in the output FIFO */
210      asm volatile( "li 10,0x202        /* Code for .CIO_STAT */
211                     mr 3, %0           /* Address of input_params */
212                     mr 4, %1           /* Address of output_params */
213                     sc"            /* Call EPPCBUG */
214        :: "g" (&input_params), "g" (&output_params) : "3", "4", "10" );
215
216      if (output_params.status)
217        goto error;
218    } while (!output_params.u.stat.output_possible);
219
220    /* Output the characters until done */
221    input_params.outbuf = &buf[i];
222    input_params.nbytes_to_output = len - i;
223 
224    asm volatile( "li 10,0x201          /* Code for .CIO_WRITE */
225                   mr 3, %0             /* Address of input_params */
226                   mr 4, %1             /* Address of output_params */
227                   sc"          /* Call EPPCBUG */
228      :: "g" (&input_params), "g" (&output_params) : "3", "4", "10" );
229
230    if (output_params.status)
231      goto error;
232
233    i += output_params.u.write.nbytes_sent;
234  }
235 
236  /* Return something */
237  m8xx.simask = simask;
238  _ISR_Enable( level );
239  return RTEMS_SUCCESSFUL;
240
241error:
242  m8xx.simask = simask;
243  _ISR_Enable( level );
244  return -1;
245}
246
247
248/*
249 *  Print functions: prototyped in bsp.h
250 *  Debug printing on Channel 1
251 */
252 
253void printk( char *fmt, ... )
254{
255  va_list  ap;                  /* points to each unnamed argument in turn */
256  static char buf[256];
257  unsigned int level;
258 
259  _CPU_ISR_Disable(level);
260 
261  va_start(ap, fmt);            /* make ap point to 1st unnamed arg */
262  vsprintf(buf, fmt, ap);       /* send output to buffer */
263 
264  BSP_output_string(buf);       /* print buffer -- Channel 1 */
265 
266  va_end(ap);               /* clean up and re-enable interrupts */
267  _CPU_ISR_Enable(level);
268}
269
270
271void BSP_output_string( char * buf )
272{
273  int len = strlen(buf);
274  int minor;                /* will be ignored */
275  rtems_status_code sc;
276
277  sc = _EPPCBug_pollWrite(minor, buf, len);
278  if (sc != RTEMS_SUCCESSFUL)
279    rtems_fatal_error_occurred (sc);
280}
281
282
283/*
284 ***************
285 * BOILERPLATE *
286 ***************
287 *
288 *  All these functions are prototyped in rtems/c/src/lib/include/console.h.
289 */
290
291/*
292 * Initialize and register the device
293 */
294rtems_device_driver console_initialize(
295  rtems_device_major_number major,
296  rtems_device_minor_number minor,
297  void *arg
298)
299{
300  rtems_status_code status;
301 
302  /*
303   * Set up TERMIOS
304   */
305  rtems_termios_initialize();
306
307  /*
308   *  Do common initialization.
309   */
310  m8xx_uart_initialize();
311 
312  /*
313   * Do device-specific initialization
314   */
315#ifndef EPPCBUG_SMC1
316  m8xx_uart_smc_initialize(SMC1_MINOR); /* /dev/tty0 */
317#endif /* EPPCBUG_SMC1 */
318
319  m8xx_uart_smc_initialize(SMC2_MINOR); /* /dev/tty1 */                             
320  m8xx_uart_scc_initialize(SCC2_MINOR); /* /dev/tty2    */
321                             
322#ifdef mpc860
323  m8xx_uart_scc_initialize(SCC3_MINOR); /* /dev/tty3    */
324  m8xx_uart_scc_initialize(SCC4_MINOR); /* /dev/tty4    */
325#endif /* mpc860 */
326
327  /*
328   * Set up interrupts
329   */
330   m8xx_uart_interrupts_initialize();
331
332  status = rtems_io_register_name ("/dev/tty0", major, SMC1_MINOR);
333  if (status != RTEMS_SUCCESSFUL)
334    rtems_fatal_error_occurred (status);
335   
336  status = rtems_io_register_name ("/dev/tty1", major, SMC2_MINOR);
337  if (status != RTEMS_SUCCESSFUL)
338    rtems_fatal_error_occurred (status);
339   
340  status = rtems_io_register_name ("/dev/tty2", major, SCC2_MINOR);
341  if (status != RTEMS_SUCCESSFUL)
342    rtems_fatal_error_occurred (status);
343   
344#ifdef mpc860
345  status = rtems_io_register_name ("/dev/tty3", major, SCC3_MINOR);
346  if (status != RTEMS_SUCCESSFUL)
347    rtems_fatal_error_occurred (status);
348                             
349  status = rtems_io_register_name ("/dev/tty4", major, SCC4_MINOR);
350  if (status != RTEMS_SUCCESSFUL)
351    rtems_fatal_error_occurred (status);
352   
353#endif /* mpc860 */
354   
355  /* Now register the RTEMS console */
356  status = rtems_io_register_name ("/dev/console", major, CONSOLE_MINOR);
357  if (status != RTEMS_SUCCESSFUL)
358    rtems_fatal_error_occurred (status);
359   
360  return RTEMS_SUCCESSFUL;
361}
362
363
364/*
365 * Open the device
366 */
367rtems_device_driver console_open(
368  rtems_device_major_number major,
369  rtems_device_minor_number minor,
370  void *arg
371)
372{
373  /* Used to track termios private data for callbacks */
374  extern struct rtems_termios_tty *ttyp[];
375
376  volatile m8xxSCCRegisters_t *sccregs;
377  rtems_status_code sc;
378  rtems_libio_open_close_args_t *args = arg;
379 
380#ifdef EPPCBUG_SMC1
381  static const rtems_termios_callbacks sccEPPCBugCallbacks = {
382    NULL,                               /* firstOpen */
383    NULL,                               /* lastClose */
384    _EPPCBug_pollRead,                  /* pollRead */
385    _EPPCBug_pollWrite,                 /* write */
386    NULL,                               /* stopRemoteTx */
387    NULL,                               /* startRemoteTx */
388    0                                   /* outputUsesInterrupts */
389  }; 
390#endif
391
392#ifdef UARTS_USE_INTERRUPTS 
393  static const rtems_termios_callbacks intrCallbacks = {
394    NULL,                               /* firstOpen */
395    NULL,                               /* lastClose */
396    NULL,                               /* pollRead */
397    m8xx_uart_write,                    /* write */
398    m8xx_uart_setAttributes,            /* setAttributes */
399    NULL,                               /* stopRemoteTx */
400    NULL,                               /* startRemoteTx */
401    1                                   /* outputUsesInterrupts */
402  };
403#else
404  static const rtems_termios_callbacks pollCallbacks = {
405    NULL,                               /* firstOpen */
406    NULL,                               /* lastClose */
407    m8xx_uart_pollRead,                 /* pollRead */
408    m8xx_uart_pollWrite,                /* write */
409    m8xx_uart_setAttributes,            /* setAttributes */
410    NULL,                               /* stopRemoteTx */
411    NULL,                               /* startRemoteTx */
412    0                                   /* outputUsesInterrupts */
413  };
414#endif
415
416  if ( (minor < SMC1_MINOR) || (minor > NUM_PORTS-1) )
417    return RTEMS_INVALID_NUMBER;
418   
419#ifdef EPPCBUG_SMC1
420  if (minor == SMC1_MINOR)
421    return rtems_termios_open (major, minor, arg, &sccEPPCBugCallbacks);
422#endif /* EPPCBUG_SMC1 */
423
424#ifdef UARTS_USE_INTERRUPTS 
425  sc = rtems_termios_open (major, minor, arg, &intrCallbacks);
426  ttyp[minor] = args->iop->data1;        /* Keep cookie returned by termios_open */
427#else
428  sc = rtems_termios_open (major, minor, arg, &pollCallbacks);
429#endif
430  return sc;
431}
432
433
434/*
435 * Close the device
436 */
437rtems_device_driver console_close(
438  rtems_device_major_number major,
439  rtems_device_minor_number minor,
440  void *arg
441)
442{
443  return rtems_termios_close (arg);
444}
445
446
447/*
448 * Read from the device
449 */
450rtems_device_driver console_read(
451  rtems_device_major_number major,
452  rtems_device_minor_number minor,
453  void *arg
454)
455{
456  return rtems_termios_read(arg);
457}
458
459
460/*
461 * Write to the device
462 */
463rtems_device_driver console_write(
464  rtems_device_major_number major,
465  rtems_device_minor_number minor,
466  void *arg
467)
468{
469  return rtems_termios_write(arg);
470}
471
472
473/*
474 * Handle ioctl request.
475 */
476rtems_device_driver console_control(
477  rtems_device_major_number major,
478  rtems_device_minor_number minor,
479  void *arg
480)
481{
482  return rtems_termios_ioctl (arg);
483}
484
Note: See TracBrowser for help on using the repository browser.