⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 console.c

📁 RTEMS (Real-Time Executive for Multiprocessor Systems) is a free open source real-time operating sys
💻 C
📖 第 1 页 / 共 2 页
字号:
/* *  console.c * *  This file contains the MBX8xx termios serial I/O package. *  Only asynchronous I/O is supported. * *  The SCCs and SMCs are assigned as follows * *   Channel     Device      Minor   Note *    SMC1      /dev/tty0      0 *    SMC2      /dev/tty1      1 *    SCC1                     2     N/A. Hardwired as ethernet port *    SCC2      /dev/tty2      3 *    SCC3      /dev/tty3      4 *    SCC4      /dev/tty4      5 * *  All ports support termios. The use of termios is recommended for real-time *  applications. Termios provides buffering and input processing. When not *  using termios, processing is limited to the substitution of LF for CR on *  input, and the output of a CR following the output of a LF character. *  Note that the terminal should not send CR/LF pairs when the return key *  is pressed, and that output lines are terminated with LF/CR, not CR/LF *  (although that would be easy to change). * *  I/O may be interrupt-driven (recommended for real-time applications) or *  polled. Polled I/O may be performed by this device driver entirely, or *  in part by EPPCBug. With EPPCBug 1.1, polled I/O is limited to the *  EPPCBug debug console. This is a limitation of the firmware. Later *  firmware may be able to do I/O through any port. This code assumes *  that the EPPCBug console is the default: SMC1. If the console and *  printk ports are set to anything else with EPPCBug polled I/O, the *  system will hang. Only port SMC1 is usable with EPPCBug polled I/O. * *  LIMITATIONS: * *  It is not possible to use different I/O modes on the different ports. The *  exception is with printk. The printk port can use a different mode from *  the other ports. If this is done, it is important not to open the printk *  port from an RTEMS application. * *  Currently, the I/O modes are determined at build time. It would be much *  better to have the mode selected at boot time based on parameters in *  NVRAM. * *  Interrupt-driven I/O requires termios. * *  TESTS: *  *  TO RUN THE TESTS, USE POLLED I/O WITHOUT TERMIOS SUPPORT. Some tests *  play with the interrupt masks and turn off I/O. Those tests will hang *  when interrupt-driven I/O is used. Other tests, such as cdtest, do I/O *  from the static constructors before the console is open. This test *  will not work with interrupt-driven I/O. Because of the buffering *  performed in termios, test output may not be in sequence.The tests *  should all be fixed to work with interrupt-driven I/O and to *  produce output in the expected sequence. Obviously, the termios test *  requires termios support in the driver. *   *  Set CONSOLE_MINOR to the appropriate device minor number in the *  config file. This allows the RTEMS application console to be different *  from the EPPBug debug console or the GDB port. *  *  This driver handles all five available serial ports: it distinguishes *  the sub-devices using minor device numbers. It is not possible to have *  other protocols running on the other ports when this driver is used as *  currently written. *   *  Based on code (alloc860.c in eth_comm port) by *  Jay Monkman (jmonkman@frasca.com), *  Copyright (C) 1998 by Frasca International, Inc. * *  Modifications by Darlene Stewart <Darlene.Stewart@iit.nrc.ca> *  and Charles-Antoine Gauthier <charles.gauthier@iit.nrc.ca>. *  Copyright (c) 2000, National Research Council of Canada * */#include <stdarg.h>#include <stdio.h>#include <bsp.h>                /* Must be before libio.h */#include <rtems/bspIo.h>#include <rtems/libio.h>#include <termios.h>#include <bsp/mbx.h>static int _EPPCBug_pollRead( int minor );static int _EPPCBug_pollWrite( int minor, const char *buf, int len );static void _BSP_output_char( char c );static rtems_status_code do_poll_read( rtems_device_major_number major, rtems_device_minor_number minor, void * arg);static rtems_status_code do_poll_write( rtems_device_major_number major, rtems_device_minor_number minor, void * arg);static void _BSP_null_char( char c ) {return;}static void serial_putchar(const char c);BSP_output_char_function_type BSP_output_char = _BSP_null_char;/* * _EPPCBug_pollRead * *  Read a character from the EPPCBug console, and return it. Return -1 *  if there is no character in the input FIFO. * *  Input parameters: *    minor - selected channel * *  Output parameters:  NONE * *  Return value: char returned as positive signed int *                -1 if no character is present in the input FIFO. */static int _EPPCBug_pollRead(  int minor){  extern volatile m8xx_t m8xx;  char c;  volatile int simask;		/* We must read and write m8xx.simask */  int retval;  ISR_Level level;    struct {    int clun;    int dlun;    char * inbuf;    int nbytes_requested;    int reserved;  } volatile input_params;    struct {    int status;    union {      struct {        int input_char_available;        int output_possible;        int break_detected;        int modem_status;      } stat;      struct {        int nbytes_received;      } read;    } u;  } volatile output_params;  retval = -1;  input_params.clun = 0;    switch( minor ) {    case SMC1_MINOR:          input_params.dlun = 0;  /* Should be 4, but doesn't work with EPPCBug 1.1 */      break;    case SMC2_MINOR:          input_params.dlun = 5;      break;    case SCC2_MINOR:          input_params.dlun = 1;      break;#ifdef mpc860    case SCC3_MINOR:          input_params.dlun = 2;      break;    case SCC4_MINOR:          input_params.dlun = 3;      break;#endif    default:          input_params.dlun = 0;      break;  }    _ISR_Disable( level );  simask = m8xx.simask;  /* Check for a char in the input FIFO using .CIO_STAT */  asm volatile( "li 10,0x202\n\                 mr 3, %0\n\                 mr 4, %1\n\                 sc"    :: "g" (&input_params), "g" (&output_params) : "3", "4", "10" );  if ( (output_params.status == 0) && output_params.u.stat.input_char_available) {      /* Read the char and return it */    input_params.inbuf = &c;    input_params.nbytes_requested = 1;      asm volatile( "li     10,0x200     /* Code for .CIO_READ */\n\                   mr    3, %0         /* Address of input_params */\n\                   mr    4, %1         /* Address of output_params */\n\                   sc"             /* Call EPPCBUG */       :: "g" (&input_params), "g" (&output_params) : "3", "4", "10" );    if ( (output_params.status == 0) && output_params.u.read.nbytes_received)      retval = (int)c;  }    m8xx.simask = simask;  _ISR_Enable( level );  return retval;}/* * _EPPCBug_pollWrite * *  Output buffer through EPPCBug. Returns only once every character has been *  sent (polled output). * *  Input parameters: *    minor - selected channel *    buf - output buffer *    len - number of chars to output * *  Output parameters:  NONE * *  Return value: IGNORED */static int _EPPCBug_pollWrite(  int minor,  const char *buf,  int len){  extern volatile m8xx_t m8xx;  volatile int simask;  int i, retval;  ISR_Level level;    struct {    int clun;    int dlun;    const char * outbuf;    int nbytes_to_output;    int reserved;  } volatile input_params;    struct {    int status;    union {      struct {        int input_char_available;        int output_possible;        int break_detected;        int modem_status;      } stat;      struct {        int nbytes_sent;      } write;    } u;  } volatile output_params;  retval = -1;  input_params.clun = 0;  input_params.reserved = 0;    switch( minor ) {    case SMC1_MINOR:          input_params.dlun = 0;  /* Should be 4, but doesn't work with EPPCBug 1.1 */      break;    case SMC2_MINOR:          input_params.dlun = 5;      break;    case SCC2_MINOR:          input_params.dlun = 1;      break;#ifdef mpc860    case SCC3_MINOR:          input_params.dlun = 2;      break;    case SCC4_MINOR:          input_params.dlun = 3;      break;#endif    default:          input_params.dlun = 0;      break;  }  i = 0;  _ISR_Disable( level );  simask = m8xx.simask;  while (i < len) {    /* Wait for space in the output buffer */    do {      /* Check for space in the output FIFO */      asm volatile( "li 10,0x202        /* Code for .CIO_STAT */\n\                     mr 3, %0           /* Address of input_params */\n\                     mr 4, %1           /* Address of output_params */\n\                     sc"            /* Call EPPCBUG */         :: "g" (&input_params), "g" (&output_params) : "3", "4", "10" );      if (output_params.status)        goto error;    } while (!output_params.u.stat.output_possible);    /* Output the characters until done */    input_params.outbuf = &buf[i];    input_params.nbytes_to_output = len - i;      asm volatile( "li 10,0x201          /* Code for .CIO_WRITE */\n\                   mr 3, %0             /* Address of input_params */\n\                   mr 4, %1             /* Address of output_params */\n\                   sc"                  /* Call EPPCBUG */       :: "g" (&input_params), "g" (&output_params) : "3", "4", "10" );    if (output_params.status)      goto error;    i += output_params.u.write.nbytes_sent;  }    /* Return something */  m8xx.simask = simask;  _ISR_Enable( level );  return RTEMS_SUCCESSFUL;error:  m8xx.simask = simask;  _ISR_Enable( level );  return -1;}/* *  do_poll_read * *  Input characters through polled I/O. Returns has soon as a character has *  been received. Otherwise, if we wait for the number of requested characters, *  we could be here forever! * *  CR is converted to LF on input. The terminal should not send a CR/LF pair *  when the return or enter key is pressed. * *  Input parameters: *    major - ignored. Should be the major number for this driver. *    minor - selected channel. *    arg->buffer - where to put the received characters. *    arg->count  - number of characters to receive before returning--Ignored. * *  Output parameters: *    arg->bytes_moved - the number of characters read. Always 1. * *  Return value: RTEMS_SUCCESSFUL * *  CANNOT BE COMBINED WITH INTERRUPT DRIVEN I/O! */static rtems_status_code do_poll_read(  rtems_device_major_number major,  rtems_device_minor_number minor,  void                    * arg){  rtems_libio_rw_args_t *rw_args = arg;  int c;#if NVRAM_CONFIGURE == 1  int (*pollRead)( int minor );    if ( (nvram->console_mode & 0x06) == 0x04 )    pollRead = _EPPCBug_pollRead;  else    pollRead = m8xx_uart_pollRead;  while( (c = (*pollRead)(minor)) == -1 );  rw_args->buffer[0] = (unsigned8)c;  if( rw_args->buffer[0] == '\r' )      rw_args->buffer[0] = '\n';  rw_args->bytes_moved = 1;  return RTEMS_SUCCESSFUL;#else#if UARTS_IO_MODE == 2#define BSP_READ  _EPPCBug_pollRead#else#define BSP_READ  m8xx_uart_pollRead#endif  while( (c = BSP_READ(minor)) == -1 );  rw_args->buffer[0] = (unsigned8)c;  if( rw_args->buffer[0] == '\r' )      rw_args->buffer[0] = '\n';  rw_args->bytes_moved = 1;  return RTEMS_SUCCESSFUL;#endif}/* *  do_poll_write * *  Output characters through polled I/O. Returns only once every character has *  been sent. * *  CR is transmitted AFTER a LF on output.  * *  Input parameters: *    major - ignored. Should be the major number for this driver. *    minor - selected channel *    arg->buffer - where to get the characters to transmit. *    arg->count  - the number of characters to transmit before returning. * *  Output parameters: *    arg->bytes_moved - the number of characters read * *  Return value: RTEMS_SUCCESSFUL * *  CANNOT BE COMBINED WITH INTERRUPT DRIVEN I/O! */static rtems_status_code do_poll_write(  rtems_device_major_number major,  rtems_device_minor_number minor,  void                    * arg){  rtems_libio_rw_args_t *rw_args = arg;  unsigned32 i;  char cr ='\r';#if NVRAM_CONFIGURE == 1  int (*pollWrite)(int minor, const char *buf, int len);    if ( (nvram->console_mode & 0x06) == 0x04 )    pollWrite = _EPPCBug_pollWrite;  else    pollWrite = m8xx_uart_pollWrite;  for( i = 0; i < rw_args->count; i++ ) {    (*pollWrite)(minor, &(rw_args->buffer[i]), 1);    if ( rw_args->buffer[i] == '\n' )      (*pollWrite)(minor, &cr, 1);  }  rw_args->bytes_moved = i;  return RTEMS_SUCCESSFUL;#else#if UARTS_IO_MODE == 2#define BSP_WRITE _EPPCBug_pollWrite#else#define BSP_WRITE m8xx_uart_pollWrite#endif  for( i = 0; i < rw_args->count; i++ ) {    BSP_WRITE(minor, &(rw_args->buffer[i]), 1);    if ( rw_args->buffer[i] == '\n' )      BSP_WRITE(minor, &cr, 1);  }  rw_args->bytes_moved = i;  return RTEMS_SUCCESSFUL;#endif}/* *  Print functions prototyped in bspIo.h */static void _BSP_output_char( char c ){  char cr = '\r';    /*    *  Can't rely on console_initialize having been called before this function   *  is used, so it may fail unless output is done through EPPC-Bug.   */#if NVRAM_CONFIGURE == 1  rtems_device_minor_number printk_minor;  /* Use NVRAM info for configuration */  printk_minor = (nvram->console_printk_port & 0x70) >> 4;  if( (nvram->console_mode & 0x30) == 0x20 ) {    _EPPCBug_pollWrite( printk_minor, &c, 1 );    if( c == '\n' )      _EPPCBug_pollWrite( printk_minor, &cr, 1 );  }  else {    m8xx_uart_pollWrite( printk_minor, &c, 1 );    if( c == '\n' )      m8xx_uart_pollWrite( PRINTK_MINOR, &cr, 1 );	}	#else  #if PRINTK_IO_MODE == 2#define PRINTK_WRITE _EPPCBug_pollWrite#else#define PRINTK_WRITE m8xx_uart_pollWrite#endif  PRINTK_WRITE( PRINTK_MINOR, &c, 1 );  if( c == '\n' )    PRINTK_WRITE( PRINTK_MINOR, &cr, 1 );    #endif}bd_t *eppcbugInfo= (bd_t *)0xdeadbeef;bd_t fakeEppcBugInfo = {  	0x42444944,		/* Should be 0x42444944 "BDID" */	sizeof(bd_t),		/* Size of this structure */	0,			/* revision of this structure */	0,			/* EPPCbug date, i.e. 0x11061997 */	0,			/* Memory start address */	0x1000000,		/* Memory (end) size in bytes */	0x28,			/* Internal Freq, in Hz */	0,			/* Bus Freq, in Hz */	0,			/* Boot device controller */	0			/* Boot device logical dev */};#define EARLY_CONSOLE#ifdef EARLY_CONSOLE#define MBX_CSR1	((volatile unsigned char *)0xfa100000)#define CSR1_COMEN	(unsigned char)0x02#define PROFF_CONS	PROFF_SMC1#define CPM_CR_CH_CONS	CPM_CR_CH_SMC1#define SMC_INDEX	0#include <bsp/commproc.h>static cpm8xx_t	*cpmp = (cpm8xx_t *)&(((immap_t *)IMAP_ADDR)->im_cpm);voidserial_init(){	volatile smc_t		*sp;	volatile smc_uart_t	*up;	volatile cbd_t	*tbdf,  *rbdf;	volatile cpm8xx_t	*cp;	unsigned int		dpaddr, memaddr;	bd_t	*bd;#if NVRAM_CONFIGURE == 1	if ( ((nvram->console_mode & 0x06) != 0x04 ) || 	     ((nvram->console_mode & 0x30) != 0x20 )) {	  /*	   * FIXME: refine this condition...	   */#endif	bd = eppcbugInfo;		cp = cpmp;	sp = (smc_t*)&(cp->cp_smc[SMC_INDEX]);	up = (smc_uart_t *)&cp->cp_dparam[PROFF_CONS];	/* Disable transmitter/receiver.	*/	sp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);	if (*MBX_CSR1 & CSR1_COMEN) {		/* COM1 is enabled.  Initialize SMC1 and use it for		 * the console port.		 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -