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

4.104.114.84.95
Last change on this file since 4385f2df was 4385f2df, checked in by Joel Sherrill <joel.sherrill@…>, on 01/04/02 at 17:40:51

2002-01-03 Ralf Corsepius <corsepiu@…>

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