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

4.115
Last change on this file since a42d8b0 was a42d8b0, checked in by Ralf Corsepius <ralf.corsepius@…>, on 02/11/11 at 12:46:34

2011-02-11 Ralf Corsépius <ralf.corsepius@…>

  • console/console.c, irq/irq.c: Use "asm" instead of "asm" for improved c99-compliance.
  • Property mode set to 100644
File size: 28.1 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 */
77#include <stdarg.h>
78#include <stdio.h>
79#include <bsp.h>                /* Must be before libio.h */
80#include <rtems/bspIo.h>
81#include <rtems/libio.h>
82#include <termios.h>
83#include <bsp/mbx.h>
84
85static int _EPPCBug_pollRead( int minor );
86static ssize_t _EPPCBug_pollWrite( int minor, const char *buf, size_t len );
87static void _BSP_output_char( char c );
88static rtems_status_code do_poll_read( rtems_device_major_number major, rtems_device_minor_number minor, void * arg);
89static rtems_status_code do_poll_write( rtems_device_major_number major, rtems_device_minor_number minor, void * arg);
90
91static void _BSP_null_char( char c ) {return;}
92static void serial_putchar(const char c);
93
94BSP_output_char_function_type     BSP_output_char = _BSP_null_char;
95BSP_polling_getchar_function_type BSP_poll_char = NULL;
96
97extern volatile m8xx_t m8xx;
98extern struct rtems_termios_tty *ttyp[];
99
100/*
101 * _EPPCBug_pollRead
102 *
103 *  Read a character from the EPPCBug console, and return it. Return -1
104 *  if there is no character in the input FIFO.
105 *
106 *  Input parameters:
107 *    minor - selected channel
108 *
109 *  Output parameters:  NONE
110 *
111 *  Return value: char returned as positive signed int
112 *                -1 if no character is present in the input FIFO.
113 */
114static int _EPPCBug_pollRead(
115  int minor
116)
117{
118  char c;
119  volatile int simask;          /* We must read and write m8xx.simask */
120  int retval;
121  ISR_Level level;
122
123  struct {
124    int clun;
125    int dlun;
126    char * inbuf;
127    int nbytes_requested;
128    int reserved;
129  } volatile input_params;
130
131  struct {
132    int status;
133    union {
134      struct {
135        int input_char_available;
136        int output_possible;
137        int break_detected;
138        int modem_status;
139      } stat;
140      struct {
141        int nbytes_received;
142      } read;
143    } u;
144  } volatile output_params;
145
146  retval = -1;
147
148  input_params.clun = 0;
149
150  switch( minor ) {
151    case SMC1_MINOR:
152      input_params.dlun = 0;  /* Should be 4, but doesn't work with EPPCBug 1.1 */
153      break;
154    case SMC2_MINOR:
155      input_params.dlun = 5;
156      break;
157    case SCC2_MINOR:
158      input_params.dlun = 1;
159      break;
160#ifdef mpc860
161    case SCC3_MINOR:
162      input_params.dlun = 2;
163      break;
164    case SCC4_MINOR:
165      input_params.dlun = 3;
166      break;
167#endif
168    default:
169      input_params.dlun = 0;
170      break;
171  }
172
173  _ISR_Disable( level );
174  simask = m8xx.simask;
175
176  /* Check for a char in the input FIFO using .CIO_STAT */
177  __asm__ volatile( "li 10,0x202\n\
178                 mr 3, %0\n\
179                 mr 4, %1\n\
180                 sc"
181    :: "g" (&input_params), "g" (&output_params) : "3", "4", "10" );
182
183  if ( (output_params.status == 0) && output_params.u.stat.input_char_available) {
184
185    /* Read the char and return it */
186    input_params.inbuf = &c;
187    input_params.nbytes_requested = 1;
188
189    __asm__ volatile( "li     10,0x200     /* Code for .CIO_READ */\n\
190                   mr    3, %0         /* Address of input_params */\n\
191                   mr    4, %1         /* Address of output_params */\n\
192                   sc"             /* Call EPPCBUG */
193      :: "g" (&input_params), "g" (&output_params) : "3", "4", "10" );
194
195    if ( (output_params.status == 0) && output_params.u.read.nbytes_received)
196      retval = (int)c;
197  }
198
199  m8xx.simask = simask;
200  _ISR_Enable( level );
201  return retval;
202}
203
204/*
205 * _EPPCBug_pollWrite
206 *
207 *  Output buffer through EPPCBug. Returns only once every character has been
208 *  sent (polled output).
209 *
210 *  Input parameters:
211 *    minor - selected channel
212 *    buf - output buffer
213 *    len - number of chars to output
214 *
215 *  Output parameters:  NONE
216 *
217 *  Return value: IGNORED
218 */
219static ssize_t _EPPCBug_pollWrite(
220  int minor,
221  const char *buf,
222  size_t len
223)
224{
225  volatile int simask;
226  int i;
227  ISR_Level level;
228
229  struct {
230    int clun;
231    int dlun;
232    const char * outbuf;
233    int nbytes_to_output;
234    int reserved;
235  } volatile input_params;
236
237  struct {
238    int status;
239    union {
240      struct {
241        int input_char_available;
242        int output_possible;
243        int break_detected;
244        int modem_status;
245      } stat;
246      struct {
247        int nbytes_sent;
248      } write;
249    } u;
250  } volatile output_params;
251
252  input_params.clun = 0;
253  input_params.reserved = 0;
254
255  switch( minor ) {
256    case SMC1_MINOR:
257      input_params.dlun = 0;  /* Should be 4, but doesn't work with EPPCBug 1.1 */
258      break;
259    case SMC2_MINOR:
260      input_params.dlun = 5;
261      break;
262    case SCC2_MINOR:
263      input_params.dlun = 1;
264      break;
265#ifdef mpc860
266    case SCC3_MINOR:
267      input_params.dlun = 2;
268      break;
269    case SCC4_MINOR:
270      input_params.dlun = 3;
271      break;
272#endif
273    default:
274      input_params.dlun = 0;
275      break;
276  }
277
278  i = 0;
279
280  _ISR_Disable( level );
281  simask = m8xx.simask;
282
283  while (i < len) {
284    /* Wait for space in the output buffer */
285    do {
286      /* Check for space in the output FIFO */
287      __asm__ volatile( "li 10,0x202        /* Code for .CIO_STAT */\n\
288                     mr 3, %0           /* Address of input_params */\n\
289                     mr 4, %1           /* Address of output_params */\n\
290                     sc"            /* Call EPPCBUG */
291        :: "g" (&input_params), "g" (&output_params) : "3", "4", "10" );
292
293      if (output_params.status)
294        goto error;
295    } while (!output_params.u.stat.output_possible);
296
297    /* Output the characters until done */
298    input_params.outbuf = &buf[i];
299    input_params.nbytes_to_output = len - i;
300
301    __asm__ volatile( "li 10,0x201          /* Code for .CIO_WRITE */\n\
302                   mr 3, %0             /* Address of input_params */\n\
303                   mr 4, %1             /* Address of output_params */\n\
304                   sc"                  /* Call EPPCBUG */
305      :: "g" (&input_params), "g" (&output_params) : "3", "4", "10" );
306
307    if (output_params.status)
308      goto error;
309
310    i += output_params.u.write.nbytes_sent;
311  }
312
313  /* Return something */
314  m8xx.simask = simask;
315  _ISR_Enable( level );
316  return len;
317
318error:
319  m8xx.simask = simask;
320  _ISR_Enable( level );
321  return -1;
322}
323
324/*
325 *  do_poll_read
326 *
327 *  Input characters through polled I/O. Returns has soon as a character has
328 *  been received. Otherwise, if we wait for the number of requested characters,
329 *  we could be here forever!
330 *
331 *  CR is converted to LF on input. The terminal should not send a CR/LF pair
332 *  when the return or enter key is pressed.
333 *
334 *  Input parameters:
335 *    major - ignored. Should be the major number for this driver.
336 *    minor - selected channel.
337 *    arg->buffer - where to put the received characters.
338 *    arg->count  - number of characters to receive before returning--Ignored.
339 *
340 *  Output parameters:
341 *    arg->bytes_moved - the number of characters read. Always 1.
342 *
343 *  Return value: RTEMS_SUCCESSFUL
344 *
345 *  CANNOT BE COMBINED WITH INTERRUPT DRIVEN I/O!
346 */
347static rtems_status_code do_poll_read(
348  rtems_device_major_number major,
349  rtems_device_minor_number minor,
350  void                    * arg
351)
352{
353  rtems_libio_rw_args_t *rw_args = arg;
354  int c;
355
356#if NVRAM_CONFIGURE == 1
357
358  int (*pollRead)( int minor );
359
360  if ( (nvram->console_mode & 0x06) == 0x04 )
361    pollRead = _EPPCBug_pollRead;
362  else
363    pollRead = m8xx_uart_pollRead;
364
365  while( (c = (*pollRead)(minor)) == -1 );
366  rw_args->buffer[0] = (uint8_t)c;
367  if( rw_args->buffer[0] == '\r' )
368      rw_args->buffer[0] = '\n';
369  rw_args->bytes_moved = 1;
370  return RTEMS_SUCCESSFUL;
371
372#else
373
374#if UARTS_IO_MODE == 2
375#define BSP_READ  _EPPCBug_pollRead
376#else
377#define BSP_READ  m8xx_uart_pollRead
378#endif
379
380  while( (c = BSP_READ(minor)) == -1 );
381  rw_args->buffer[0] = (uint8_t)c;
382  if( rw_args->buffer[0] == '\r' )
383      rw_args->buffer[0] = '\n';
384  rw_args->bytes_moved = 1;
385  return RTEMS_SUCCESSFUL;
386
387#endif
388}
389
390/*
391 *  do_poll_write
392 *
393 *  Output characters through polled I/O. Returns only once every character has
394 *  been sent.
395 *
396 *  CR is transmitted AFTER a LF on output.
397 *
398 *  Input parameters:
399 *    major - ignored. Should be the major number for this driver.
400 *    minor - selected channel
401 *    arg->buffer - where to get the characters to transmit.
402 *    arg->count  - the number of characters to transmit before returning.
403 *
404 *  Output parameters:
405 *    arg->bytes_moved - the number of characters read
406 *
407 *  Return value: RTEMS_SUCCESSFUL
408 *
409 *  CANNOT BE COMBINED WITH INTERRUPT DRIVEN I/O!
410 */
411static rtems_status_code do_poll_write(
412  rtems_device_major_number major,
413  rtems_device_minor_number minor,
414  void                    * arg
415)
416{
417  rtems_libio_rw_args_t *rw_args = arg;
418  uint32_t   i;
419  char cr ='\r';
420
421#if NVRAM_CONFIGURE == 1
422
423  ssize_t (*pollWrite)(int minor, const char *buf, size_t len);
424
425  if ( (nvram->console_mode & 0x06) == 0x04 )
426    pollWrite = _EPPCBug_pollWrite;
427  else
428    pollWrite = m8xx_uart_pollWrite;
429
430  for( i = 0; i < rw_args->count; i++ ) {
431    (*pollWrite)(minor, &(rw_args->buffer[i]), 1);
432    if ( rw_args->buffer[i] == '\n' )
433      (*pollWrite)(minor, &cr, 1);
434  }
435  rw_args->bytes_moved = i;
436  return RTEMS_SUCCESSFUL;
437
438#else
439
440#if UARTS_IO_MODE == 2
441#define BSP_WRITE _EPPCBug_pollWrite
442#else
443#define BSP_WRITE m8xx_uart_pollWrite
444#endif
445
446  for( i = 0; i < rw_args->count; i++ ) {
447    BSP_WRITE(minor, &(rw_args->buffer[i]), 1);
448    if ( rw_args->buffer[i] == '\n' )
449      BSP_WRITE(minor, &cr, 1);
450  }
451  rw_args->bytes_moved = i;
452  return RTEMS_SUCCESSFUL;
453
454#endif
455}
456
457/*
458 *  Print functions prototyped in bspIo.h
459 */
460
461static void _BSP_output_char( char c )
462{
463  char cr = '\r';
464
465  /*
466   *  Can't rely on console_initialize having been called before this function
467   *  is used, so it may fail unless output is done through EPPC-Bug.
468   */
469#if NVRAM_CONFIGURE == 1
470
471  rtems_device_minor_number printk_minor;
472
473  /* Use NVRAM info for configuration */
474  printk_minor = (nvram->console_printk_port & 0x70) >> 4;
475  if( (nvram->console_mode & 0x30) == 0x20 ) {
476    _EPPCBug_pollWrite( printk_minor, &c, 1 );
477    if( c == '\n' )
478      _EPPCBug_pollWrite( printk_minor, &cr, 1 );
479  }
480  else {
481    m8xx_uart_pollWrite( printk_minor, &c, 1 );
482    if( c == '\n' )
483      m8xx_uart_pollWrite( PRINTK_MINOR, &cr, 1 );
484        }
485
486#else
487
488#if PRINTK_IO_MODE == 2
489#define PRINTK_WRITE _EPPCBug_pollWrite
490#else
491#define PRINTK_WRITE m8xx_uart_pollWrite
492#endif
493
494  PRINTK_WRITE( PRINTK_MINOR, &c, 1 );
495  if( c == '\n' )
496    PRINTK_WRITE( PRINTK_MINOR, &cr, 1 );
497
498#endif
499}
500
501bd_t *eppcbugInfo= (bd_t *)0xdeadbeef;
502bd_t fakeEppcBugInfo = {
503        0x42444944,             /* Should be 0x42444944 "BDID" */
504        sizeof(bd_t),           /* Size of this structure */
505        0,                      /* revision of this structure */
506        0,                      /* EPPCbug date, i.e. 0x11061997 */
507        0,                      /* Memory start address */
508        0x1000000,              /* Memory (end) size in bytes */
509        0x28,                   /* Internal Freq, in Hz */
510        0,                      /* Bus Freq, in Hz */
511        0,                      /* Boot device controller */
512        0                       /* Boot device logical dev */
513};
514
515#define EARLY_CONSOLE
516#ifdef EARLY_CONSOLE
517
518#define MBX_CSR1        ((volatile unsigned char *)0xfa100000)
519#define CSR1_COMEN      (unsigned char)0x02
520#define PROFF_CONS      PROFF_SMC1
521#define CPM_CR_CH_CONS  CPM_CR_CH_SMC1
522#define SMC_INDEX       0
523
524#include <bsp/commproc.h>
525
526static cpm8xx_t *cpmp = (cpm8xx_t *)&(((immap_t *)IMAP_ADDR)->im_cpm);
527
528void
529serial_init(void)
530{
531        volatile smc_t          *sp;
532        volatile smc_uart_t     *up;
533        volatile cbd_t  *tbdf,  *rbdf;
534        volatile cpm8xx_t       *cp;
535        unsigned int            dpaddr, memaddr;
536        bd_t    *bd;
537
538#if NVRAM_CONFIGURE == 1
539        if ( ((nvram->console_mode & 0x06) != 0x04 ) ||
540             ((nvram->console_mode & 0x30) != 0x20 )) {
541          /*
542           * FIXME: refine this condition...
543           */
544#endif
545        bd = eppcbugInfo;
546
547        cp = cpmp;
548        sp = (smc_t*)&(cp->cp_smc[SMC_INDEX]);
549        up = (smc_uart_t *)&cp->cp_dparam[PROFF_CONS];
550
551        /* Disable transmitter/receiver.
552        */
553        sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
554
555        if (*MBX_CSR1 & CSR1_COMEN) {
556                /* COM1 is enabled.  Initialize SMC1 and use it for
557                 * the console port.
558                 */
559
560                /* Enable SDMA.
561                */
562                ((immap_t *)IMAP_ADDR)->im_siu_conf.sc_sdcr = 1;
563
564                /* Use Port B for SMCs instead of other functions.
565                */
566                cp->cp_pbpar |= 0x00000cc0;
567                cp->cp_pbdir &= ~0x00000cc0;
568                cp->cp_pbodr &= ~0x00000cc0;
569
570                /* Allocate space for two buffer descriptors in the DP ram.
571                 * For now, this address seems OK, but it may have to
572                 * change with newer versions of the firmware.
573                 */
574                dpaddr = 0x0800;
575
576                /* Grab a few bytes from the top of memory.  EPPC-Bug isn't
577                 * running any more, so we can do this.
578                 */
579                memaddr = (bd->bi_memsize - 32) & ~15;
580
581                /* Set the physical address of the host memory buffers in
582                 * the buffer descriptors.
583                 */
584                rbdf = (cbd_t *)&cp->cp_dpmem[dpaddr];
585                rbdf->cbd_bufaddr = memaddr;
586                rbdf->cbd_sc = 0;
587                tbdf = rbdf + 1;
588                tbdf->cbd_bufaddr = memaddr+4;
589                tbdf->cbd_sc = 0;
590
591                /* Set up the uart parameters in the parameter ram.
592                */
593                up->smc_rbase = dpaddr;
594                up->smc_tbase = dpaddr+sizeof(cbd_t);
595                up->smc_rfcr = SMC_EB;
596                up->smc_tfcr = SMC_EB;
597
598                /* Set UART mode, 8 bit, no parity, one stop.
599                 * Enable receive and transmit.
600                 */
601                sp->smc_smcmr = smcr_mk_clen(9) |  SMCMR_SM_UART;
602
603                /* Mask all interrupts and remove anything pending.
604                */
605                sp->smc_smcm = 0;
606                sp->smc_smce = 0xff;
607
608                /* Set up the baud rate generator.
609                 * See 8xx_io/commproc.c for details.
610                 */
611                cp->cp_simode = 0x10000000;
612                cp->cp_brgc1 =
613                        ((((bd->bi_intfreq * 1000000)/16) / 9600) << 1) | CPM_BRG_EN;
614
615                /* Enable SMC1 for console output.
616                */
617                *MBX_CSR1 &= ~CSR1_COMEN;
618        }
619        else {
620                /* SMCx is used as console port.
621                */
622                tbdf = (cbd_t *)&cp->cp_dpmem[up->smc_tbase];
623                rbdf = (cbd_t *)&cp->cp_dpmem[up->smc_rbase];
624
625                /* Issue a stop transmit, and wait for it.
626                */
627                cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_CONS,
628                                        CPM_CR_STOP_TX) | CPM_CR_FLG;
629                while (cp->cp_cpcr & CPM_CR_FLG);
630        }
631
632        /* Make the first buffer the only buffer.
633        */
634        tbdf->cbd_sc |= BD_SC_WRAP;
635        rbdf->cbd_sc |= BD_SC_EMPTY | BD_SC_WRAP;
636
637        /* Single character receive.
638        */
639        up->smc_mrblr = 1;
640        up->smc_maxidl = 0;
641
642        /* Initialize Tx/Rx parameters.
643        */
644        cp->cp_cpcr = mk_cr_cmd(CPM_CR_CH_CONS, CPM_CR_INIT_TRX) | CPM_CR_FLG;
645        while (cp->cp_cpcr & CPM_CR_FLG);
646
647        /* Enable transmitter/receiver.
648        */
649        sp->smc_smcmr |= SMCMR_REN | SMCMR_TEN;
650#if NVRAM_CONFIGURE == 1
651        }
652        else {
653          const char bootmsg_text[]= "using EPPC bug for console I/O\n";
654          _EPPCBug_pollWrite((nvram->console_printk_port & 0x70) >> 4,
655                             bootmsg_text,
656                             sizeof(bootmsg_text)-1);
657        }
658#endif
659#if NVRAM_CONFIGURE == 1
660        if ((nvram->console_mode & 0x30) == 0x20 ) {
661          BSP_output_char = _BSP_output_char;
662        }
663        else {
664          BSP_output_char = serial_putchar;
665        }
666#else
667
668        BSP_output_char = serial_putchar;
669#endif
670}
671
672void
673serial_putchar(const char c)
674{
675        volatile cbd_t          *tbdf;
676        volatile char           *buf;
677        volatile smc_uart_t     *up;
678
679        up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_CONS];
680        tbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_tbase];
681
682        /* Wait for last character to go.
683        */
684        buf = (char *)tbdf->cbd_bufaddr;
685        while (tbdf->cbd_sc & BD_SC_READY);
686
687        *buf = c;
688        tbdf->cbd_datlen = 1;
689        tbdf->cbd_sc |= BD_SC_READY;
690}
691
692char
693serial_getc(void)
694{
695        volatile cbd_t          *rbdf;
696        volatile char           *buf;
697        volatile smc_uart_t     *up;
698        char                    c;
699
700        up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_CONS];
701        rbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_rbase];
702
703        /* Wait for character to show up.
704        */
705        buf = (char *)rbdf->cbd_bufaddr;
706        while (rbdf->cbd_sc & BD_SC_EMPTY);
707        c = *buf;
708        rbdf->cbd_sc |= BD_SC_EMPTY;
709
710        return(c);
711}
712
713int
714serial_tstc(void)
715{
716        volatile cbd_t          *rbdf;
717        volatile smc_uart_t     *up;
718
719        up = (smc_uart_t *)&cpmp->cp_dparam[PROFF_CONS];
720        rbdf = (cbd_t *)&cpmp->cp_dpmem[up->smc_rbase];
721
722        return(!(rbdf->cbd_sc & BD_SC_EMPTY));
723}
724
725#endif
726/*
727 ***************
728 * BOILERPLATE *
729 ***************
730 *
731 *  All these functions are prototyped in rtems/c/src/lib/include/console.h.
732 */
733
734/*
735 * Initialize and register the device
736 */
737rtems_device_driver console_initialize(
738  rtems_device_major_number major,
739  rtems_device_minor_number minor,
740  void *arg
741)
742{
743  rtems_status_code status;
744  rtems_device_minor_number console_minor;
745
746  /*
747   * Set up TERMIOS if needed
748   */
749#if NVRAM_CONFIGURE == 1
750  /* Use NVRAM info for configuration */
751  console_minor = nvram->console_printk_port & 0x07;
752
753  if ( nvram->console_mode & 0x01 )
754    /* termios */
755    rtems_termios_initialize ();
756
757  /*
758   *  Do common initialization.
759   */
760  m8xx_uart_initialize();
761
762  /*
763   * Do device-specific initialization
764   */
765  if ( !nvram->eppcbug_smc1 &&
766    ( ((nvram->console_mode & 0x30) != 0x20) ||
767     (((nvram->console_printk_port & 0x30) >> 4) != SMC1_MINOR) ) )
768    m8xx_uart_smc_initialize(SMC1_MINOR); /* /dev/tty0 */
769
770  if ( ((nvram->console_mode & 0x30) != 0x20) ||
771      (((nvram->console_printk_port & 0x30) >> 4) != SMC2_MINOR) )
772    m8xx_uart_smc_initialize(SMC2_MINOR); /* /dev/tty1 */
773
774  if ( ((nvram->console_mode & 0x30) != 0x20) ||
775      (((nvram->console_printk_port & 0x30) >> 4) != SCC2_MINOR) )
776    m8xx_uart_scc_initialize(SCC2_MINOR); /* /dev/tty2    */
777
778#ifdef mpc860
779
780  if ( ((nvram->console_mode & 0x30) != 0x20) ||
781      (((nvram->console_printk_port & 0x30) >> 4) != SCC3_MINOR) )
782    m8xx_uart_scc_initialize(SCC3_MINOR); /* /dev/tty3    */
783
784  if ( ((nvram->console_mode & 0x30) != 0x20) ||
785      (((nvram->console_printk_port & 0x30) >> 4) != SCC4_MINOR) )
786    m8xx_uart_scc_initialize(SCC4_MINOR); /* /dev/tty4    */
787
788#endif /* mpc860 */
789  BSP_output_char = _BSP_output_char;
790#else /* NVRAM_CONFIGURE != 1 */
791
792    console_minor = CONSOLE_MINOR;
793
794#if UARTS_USE_TERMIOS == 1
795
796    rtems_termios_initialize ();
797
798#endif /* UARTS_USE_TERMIOS */
799
800  /*
801   *  Do common initialization.
802   */
803  m8xx_uart_initialize();
804
805  /*
806   * Do device-specific initialization
807   */
808#if !defined(EPPCBUG_SMC1) && ( PRINTK_IO_MODE != 2 || PRINTK_MINOR != SMC1_MINOR )
809  m8xx_uart_smc_initialize(SMC1_MINOR); /* /dev/tty0 */
810#endif
811
812#if PRINTK_IO_MODE != 2 || PRINTK_MINOR != SMC2_MINOR
813  m8xx_uart_smc_initialize(SMC2_MINOR); /* /dev/tty1 */
814#endif
815
816  #if PRINTK_IO_MODE != 2 || PRINTK_MINOR != SCC2_MINOR
817  m8xx_uart_scc_initialize(SCC2_MINOR); /* /dev/tty2    */
818   #endif
819
820#ifdef mpc860
821
822#if PRINTK_IO_MODE != 2 || PRINTK_MINOR != SCC3_MINOR
823  m8xx_uart_scc_initialize(SCC3_MINOR); /* /dev/tty3    */
824#endif
825
826#if PRINTK_IO_MODE != 2 || PRINTK_MINOR != SCC4_MINOR
827  m8xx_uart_scc_initialize(SCC4_MINOR); /* /dev/tty4    */
828#endif
829
830#endif /* mpc860 */
831
832  BSP_output_char = _BSP_output_char;
833
834#endif /* NVRAM_CONFIGURE != 1 */
835
836  status = rtems_io_register_name ("/dev/tty0", major, SMC1_MINOR);
837  if (status != RTEMS_SUCCESSFUL)
838    rtems_fatal_error_occurred (status);
839
840  status = rtems_io_register_name ("/dev/tty1", major, SMC2_MINOR);
841  if (status != RTEMS_SUCCESSFUL)
842    rtems_fatal_error_occurred (status);
843
844  status = rtems_io_register_name ("/dev/tty2", major, SCC2_MINOR);
845  if (status != RTEMS_SUCCESSFUL)
846    rtems_fatal_error_occurred (status);
847
848#ifdef mpc860
849  status = rtems_io_register_name ("/dev/tty3", major, SCC3_MINOR);
850  if (status != RTEMS_SUCCESSFUL)
851    rtems_fatal_error_occurred (status);
852
853  status = rtems_io_register_name ("/dev/tty4", major, SCC4_MINOR);
854  if (status != RTEMS_SUCCESSFUL)
855    rtems_fatal_error_occurred (status);
856
857#endif /* mpc860 */
858
859  /* Now register the RTEMS console */
860  status = rtems_io_register_name ("/dev/console", major, console_minor);
861  if (status != RTEMS_SUCCESSFUL)
862    rtems_fatal_error_occurred (status);
863
864  return RTEMS_SUCCESSFUL;
865}
866
867/*
868 * Open the device
869 */
870rtems_device_driver console_open(
871  rtems_device_major_number major,
872  rtems_device_minor_number minor,
873  void *arg
874)
875{
876#if NVRAM_CONFIGURE == 1
877  /* Used to track termios private data for callbacks */
878  rtems_libio_open_close_args_t *args = arg;
879  static const rtems_termios_callbacks sccEPPCBugCallbacks = {
880    NULL,                               /* firstOpen */
881    NULL,                               /* lastClose */
882    _EPPCBug_pollRead,                  /* pollRead */
883    _EPPCBug_pollWrite,                 /* write */
884    NULL,                               /* stopRemoteTx */
885    NULL,                               /* startRemoteTx */
886    0                                   /* outputUsesInterrupts */
887  };
888#endif
889  static const rtems_termios_callbacks pollCallbacks = {
890    NULL,                               /* firstOpen */
891    NULL,                               /* lastClose */
892    m8xx_uart_pollRead,                 /* pollRead */
893    m8xx_uart_pollWrite,                /* write */
894    m8xx_uart_setAttributes,            /* setAttributes */
895    NULL,                               /* stopRemoteTx */
896    NULL,                               /* startRemoteTx */
897    0                                   /* outputUsesInterrupts */
898  };
899  rtems_status_code sc;
900
901#if (NVRAM_CONFIGURE == 1) || \
902    ((NVRAM_CONFIGURE != 1) && (UARTS_USE_TERMIOS == 1) && \
903      (UARTS_IO_MODE == 1))
904
905  static const rtems_termios_callbacks intrCallbacks = {
906    NULL,                               /* firstOpen */
907    NULL,                               /* lastClose */
908    NULL,                               /* pollRead */
909    m8xx_uart_write,                    /* write */
910    m8xx_uart_setAttributes,            /* setAttributes */
911    NULL,                               /* stopRemoteTx */
912    NULL,                               /* startRemoteTx */
913    1                                   /* outputUsesInterrupts */
914  };
915#endif
916
917  if ( minor > NUM_PORTS-1 )
918    return RTEMS_INVALID_NUMBER;
919
920#if NVRAM_CONFIGURE == 1
921
922  /* Use NVRAM info for configuration */
923  if ( nvram->console_mode & 0x01 ) {
924    /* Use termios */
925    if ( (nvram->console_mode & 0x06) == 0x02 ) {
926      /* interrupt-driven I/O */
927      sc = rtems_termios_open( major, minor, arg, &intrCallbacks );
928      ttyp[minor] = args->iop->data1;        /* Keep cookie returned by termios_open */
929      return sc;
930    }
931    else if ( (nvram->console_mode & 0x06) == 0x04 )
932      /* polled I/O through EPPC-Bug, better be through SMC1 */
933      return rtems_termios_open( major, minor, arg, &sccEPPCBugCallbacks );
934    else
935      /* normal polled I/O */
936      return rtems_termios_open( major, minor, arg, &pollCallbacks );
937  }
938  else
939    /* no termios -- default to polled I/O */
940    return RTEMS_SUCCESSFUL;
941
942#else /* NVRAM_CONFIGURE != 1 */
943
944#if UARTS_USE_TERMIOS == 1
945
946#if UARTS_IO_MODE == 2    /* EPPCBug polled I/O with termios */
947  sc = rtems_termios_open( major, minor, arg, &sccEPPCBugCallbacks );
948#elif UARTS_IO_MODE == 1  /* RTEMS interrupt-driven I/O with termios */
949  sc = rtems_termios_open( major, minor, arg, &intrCallbacks );
950  ttyp[minor] = args->iop->data1;        /* Keep cookie returned by termios_open */
951#else                     /* RTEMS polled I/O with termios */
952  sc = rtems_termios_open( major, minor, arg, &pollCallbacks );
953#endif
954
955#else /* UARTS_USE_TERMIOS != 1 */
956  /* no termios -- default to polled I/O */
957  sc = RTEMS_SUCCESSFUL;
958#endif /* UARTS_USE_TERMIOS != 1 */
959
960  return sc;
961
962#endif /* NVRAM_CONFIGURE != 1 */
963}
964
965/*
966 * Close the device
967 */
968rtems_device_driver console_close(
969  rtems_device_major_number major,
970  rtems_device_minor_number minor,
971  void *arg
972)
973{
974  if ( minor > NUM_PORTS-1 )
975    return RTEMS_INVALID_NUMBER;
976
977#if NVRAM_CONFIGURE == 1
978
979  /* Use NVRAM info for configuration */
980  if ( nvram->console_mode & 0x01 )
981    /* use termios */
982    return rtems_termios_close( arg );
983  else
984    /* no termios */
985    return RTEMS_SUCCESSFUL;
986
987#else /* NVRAM_CONFIGURE != 1 */
988
989#if UARTS_USE_TERMIOS == 1
990  return rtems_termios_close( arg );
991#else
992  return RTEMS_SUCCESSFUL;
993#endif
994
995#endif /* NVRAM_CONFIGURE != 1 */
996}
997
998/*
999 * Read from the device
1000 */
1001rtems_device_driver console_read(
1002  rtems_device_major_number major,
1003  rtems_device_minor_number minor,
1004  void *arg
1005)
1006{
1007  if ( minor > NUM_PORTS-1 )
1008    return RTEMS_INVALID_NUMBER;
1009
1010#if NVRAM_CONFIGURE == 1
1011
1012  /* Use NVRAM info for configuration */
1013  if ( nvram->console_mode & 0x01 )
1014    /* use termios */
1015    return rtems_termios_read( arg );
1016  else
1017    /* no termios -- default to polled */
1018    return do_poll_read( major, minor, arg );
1019
1020#else
1021
1022#if UARTS_USE_TERMIOS == 1
1023  return rtems_termios_read( arg );
1024#else
1025  return do_poll_read( major, minor, arg );
1026#endif
1027
1028#endif
1029}
1030
1031/*
1032 * Write to the device
1033 */
1034rtems_device_driver console_write(
1035  rtems_device_major_number major,
1036  rtems_device_minor_number minor,
1037  void *arg
1038)
1039{
1040  if ( minor > NUM_PORTS-1 )
1041    return RTEMS_INVALID_NUMBER;
1042
1043#if NVRAM_CONFIGURE == 1
1044
1045  /* Use NVRAM info for configuration */
1046  if ( nvram->console_mode & 0x01 )
1047    /* use termios */
1048    return rtems_termios_write( arg );
1049  else
1050    /* no termios -- default to polled */
1051    return do_poll_write( major, minor, arg );
1052
1053#else
1054
1055#if UARTS_USE_TERMIOS == 1
1056  return rtems_termios_write( arg );
1057#else
1058    /* no termios -- default to polled */
1059  return do_poll_write( major, minor, arg );
1060#endif
1061
1062#endif
1063}
1064
1065/*
1066 * Handle ioctl request.
1067 */
1068rtems_device_driver console_control(
1069  rtems_device_major_number major,
1070  rtems_device_minor_number minor,
1071  void *arg
1072)
1073{
1074  if ( minor > NUM_PORTS-1 )
1075    return RTEMS_INVALID_NUMBER;
1076
1077#if NVRAM_CONFIGURE == 1
1078
1079  /* Uuse NVRAM info for configuration */
1080  if ( nvram->console_mode & 0x01 )
1081    /* termios */
1082    return rtems_termios_ioctl( arg );
1083  else
1084    /* no termios -- default to polled */
1085    return RTEMS_SUCCESSFUL;
1086
1087#else
1088
1089#if UARTS_USE_TERMIOS == 1
1090  return rtems_termios_ioctl( arg );
1091#else
1092  return RTEMS_SUCCESSFUL;
1093#endif
1094
1095#endif
1096}
1097
1098/*
1099 *  Support routine for console-generic
1100 */
1101
1102int mbx8xx_console_get_configuration(void)
1103{
1104#if NVRAM_CONFIGURE == 1
1105  return nvram->console_mode;
1106#else
1107#if UARTS_IO_MODE == 1
1108  return 0x02;
1109#else
1110  return 0;
1111#endif
1112#endif
1113
1114}
Note: See TracBrowser for help on using the repository browser.