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

4.115
Last change on this file since a2ba004 was a2ba004, checked in by Sebastian Huber <sebastian.huber@…>, on 03/16/15 at 18:31:04

bsp/mbx8xx: Fix warnings

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