summaryrefslogblamecommitdiffstats
path: root/c/src/lib/libbsp/powerpc/score603e/console/console.c
blob: 5ae61ea9db3fc17a6b480f7643a9e08d07a23f23 (plain) (tree)
1
2
3
4
5
6
7
8
9






                                                                            
                            
                                                    


                                                           
                                         







                        
                        
 
  

                                                              



                                                                
                              





                                          
 

       
                              



                                              

                               



                                         

                       

                                     
 




                                                          
 







                                   
 







                                  
 







                                   
 








                                    










                               
 

                                         
   





                                 
                      

                                            
 



                                                    
                                                      








                                          
 







                                                              
                                   

   
    



                                                         
                                                                    
 
                         
 





                                

      
































                                                                    






                                                                  



                                           
 






                                                                   
                                                           









                                                                   
    




                                                                      

                                               
















                                                
                              

                  
               

                 
                                

                                         

                       

































































                                                               























                                                                          




















                                           
                               

                            
 



                                                                   
                                          

                                        
                                  






                                                        
 



                                                        











                                                                


                                        
                              
                                       

   

                                      
                            


                                     

                                                                     

                                                                
/*
 *  This file contains the TTY driver for the serial ports on the SCORE603e.
 *
 *  This driver uses the termios pseudo driver.
 *
 *  Currently only polled mode is supported.
 *
 *  COPYRIGHT (c) 1989-2009.
 *  On-Line Applications Research Corporation (OAR).
 *
 *  The license and distribution terms for this file may be
 *  found in the file LICENSE in this distribution or at
 *  http://www.rtems.org/license/LICENSE.
 */

#include <bsp.h>
#include <rtems/libio.h>
#include <stdlib.h>
#include <assert.h>

#include "consolebsp.h"
#include <rtems/bspIo.h>

/*
 * The Port Used for the Console interface is based upon which
 * debugger is being used.  The SDS debugger uses a binary
 * interface on port 0 as part of the debugger.  Thus port 0 can
 * not be used as the console port for the SDS debugger.
 */

#define USE_FOR_CONSOLE_DEF  0
int USE_FOR_CONSOLE = USE_FOR_CONSOLE_DEF;

/*
 *
 *  Console Device Driver Entry Points
 */

/* PAGE
 *
 *  console_inbyte_nonblocking
 *
 *  Console Termios polling input entry point.
 */

int console_inbyte_nonblocking(
  int minor
)
{
  int                       port = minor;

  /*
   * verify port Number
   */
  assert ( port < NUM_Z85C30_PORTS );

  /*
   * return a character from the 85c30 port.
   */
  return inbyte_nonblocking_85c30( &Ports_85C30[ port ] );
}

rtems_device_driver console_close(
  rtems_device_major_number major,
  rtems_device_minor_number minor,
  void                    * arg
)
{
  return rtems_termios_close (arg);
}

rtems_device_driver console_read(
  rtems_device_major_number major,
  rtems_device_minor_number minor,
  void                    * arg
)
{
  return rtems_termios_read (arg);
}

rtems_device_driver console_write(
  rtems_device_major_number major,
  rtems_device_minor_number minor,
  void                    * arg
)
{
  return rtems_termios_write (arg);
}

rtems_device_driver console_control(
  rtems_device_major_number major,
  rtems_device_minor_number minor,
  void                    * arg
)
{
  return rtems_termios_ioctl (arg);
}

/*
 *  Interrupt driven console IO
 */

#if CONSOLE_USE_INTERRUPTS

rtems_isr console_isr(
  rtems_vector_number vector
)
{
  int  i;

  for (i=0; i < NUM_Z85C30_PORTS; i++){
      ISR_85c30_Async( &Ports_85C30[i] );
  }
}

void console_exit()
{
  int i;
  volatile Ring_buffer_t *buffer;
  uint32_t         ch;

  for ( i=0 ; i < NUM_Z85C30_PORTS ; i++ ) {

    buffer = &( Ports_85C30[i].Protocol->TX_Buffer);

    while ( !Ring_buffer_Is_empty( buffer ) ) {
      Ring_buffer_Remove_character( buffer, ch );
      outbyte_polled_85c30( Ports_85C30[i].ctrl, ch );
    }
  }
}

void console_initialize_interrupts( void )
{
  volatile Ring_buffer_t     *buffer;
  Console_Protocol  *protocol;
  int               i;

  for ( i=0 ; i < NUM_Z85C30_PORTS ; i++ ) {
    protocol = Ports_85C30[i].Protocol;

    /*
     * Initialize the ring buffer and set to not transmitting.
     */
    buffer = &protocol->TX_Buffer;
    Ring_buffer_Initialize( buffer );
    protocol->Is_TX_active = false;
  }

  /*
   * Connect each vector to the interupt service routine.
   */
  for (i=0; i < NUM_Z85C30_CHIPS; i++)
    set_vector( console_isr, Chips_85C30[i].vector, 1 );
  #warning "Install interrupts using proper method for PIC vectors."

  atexit( console_exit );

}
void console_outbyte_interrupts(
  const Port_85C30_info *Port,
  char ch
);

#endif

/* PAGE
 *
 *  console_initialize
 *
 *  Routine called to initialize the console device driver.
 */
rtems_device_driver console_initialize(
  rtems_device_major_number  major,
  rtems_device_minor_number  minor,
  void                      *arg
)
{
  rtems_status_code          status;
  rtems_device_minor_number  console;
  int                        port, chip, p0,p1;

  /*
   * initialize the termio interface.
   */
  rtems_termios_initialize();

  /*
   *  Register Device Names
   */
  console = USE_FOR_CONSOLE;
  status = rtems_io_register_name( "/dev/console", major, console );
  if (status != RTEMS_SUCCESSFUL)
    rtems_fatal_error_occurred(status);

  /*
   *  Initialize Hardware
   */

/*
 * INITIALIZE_COM_PORTS is defined in the linker script.  If it is
 * true all serial chips on the board are to be reset at startup
 * otherwise the reset is assumed to occur elsewhere (ie. in the
 * debugger...)
 */
#if ( INITIALIZE_COM_PORTS )
  /*
   * Force to perform a hardware reset w/o
   * Master interrupt enable via register 9
   */

  for (port=0; port<NUM_Z85C30_PORTS; port++){
    p0 = port;
    port++;
    p1 = port;
    Reset_85c30_chip( Ports_85C30[p0].ctrl, Ports_85C30[p1].ctrl );
  }
#else
  /* TEMP - To see if this makes a diff with the new ports.
   *        Never reset chip 1 when using the chip as a monitor
   */
  for (port=2; port<NUM_Z85C30_PORTS; port++){
    p0 = port;
    port++;
    p1 = port;
    Reset_85c30_chip( Ports_85C30[p0].ctrl, Ports_85C30[p1].ctrl );
  }
#endif

  /*
   * Initialize each port.
   * Note:  the ports are numbered such that 0,1 are on the first chip
   *        2,3 are on the second ....
   */

  for (port=1; port<NUM_Z85C30_PORTS; port++) {
   chip = port >> 1;
    initialize_85c30_port( &Ports_85C30[port] );
  }

#if CONSOLE_USE_INTERRUPTS
  console_initialize_interrupts();
#endif

  return RTEMS_SUCCESSFUL;
}

/* PAGE
 *
 *  console_write_support
 *
 *  Console Termios output entry point.
 *
 */
ssize_t console_write_support(
  int   minor,
  const char *buf,
  size_t   len)
{
  int nwrite = 0;
  volatile uint8_t         *csr;
  int                       port = minor;

  /*
   * verify port Number
   */
  assert ( port < NUM_Z85C30_PORTS );

  /*
   * Set the csr based upon the port number.
   */
  csr = Ports_85C30[ port ].ctrl;

  /*
   * poll each byte in the string out of the port.
   */
  while (nwrite < len) {
#if (CONSOLE_USE_INTERRUPTS)
    console_outbyte_interrupts( &Ports_85C30[ port ], *buf++ );
#else
    outbyte_polled_85c30( csr, *buf++ );
#endif
   nwrite++;
  }

  /*
   * return the number of bytes written.
   */
  return nwrite;
}

/* PAGE
 *
 *  console_open
 *
 *  open a port as a termios console.
 *
 */
rtems_device_driver console_open(
  rtems_device_major_number major,
  rtems_device_minor_number minor,
  void                    * arg
)
{
  rtems_status_code sc;
  int               port = minor;
#if (CONSOLE_USE_INTERRUPTS)
  rtems_libio_open_close_args_t *args = arg;
  static const rtems_termios_callbacks intrCallbacks = {
    NULL,                       /* firstOpen */
    NULL,                       /* lastClose */
    NULL,                       /* pollRead */
    console_write_support,      /* write */
    NULL,                       /* setAttributes */
    NULL,                       /* stopRemoteTx */
    NULL,                       /* startRemoteTx */
    1                           /* outputUsesInterrupts */
  };
#else
  static const rtems_termios_callbacks pollCallbacks = {
    NULL,                       /* firstOpen */
    NULL,                       /* lastClose */
    console_inbyte_nonblocking, /* pollRead */
    console_write_support,      /* write */
    NULL,                       /* setAttributes */
    NULL,                       /* stopRemoteTx */
    NULL,                       /* startRemoteTx */
    0                           /* outputUsesInterrupts */
  };
#endif

  /*
   * Verify the minor number is valid.
   */
  if (minor < 0)
    return RTEMS_INVALID_NUMBER;

  if ( port > NUM_Z85C30_PORTS )
     return RTEMS_INVALID_NUMBER;

  /*
   *  open the port as a termios console driver.
   */

#if (CONSOLE_USE_INTERRUPTS)
   sc = rtems_termios_open( major, minor, arg, &intrCallbacks );

   Ports_85C30[ minor ].Protocol->console_termios_data = args->iop->data1;
#else
   sc = rtems_termios_open( major, minor, arg, &pollCallbacks );
#endif

  return sc;
}

#if (CONSOLE_USE_INTERRUPTS)

/*
 *  console_outbyte_interrupts
 *
 *  This routine transmits a character out.
 *
 *  Input parameters:
 *    port - port to transmit character to
 *    ch  - character to be transmitted
 *
 *  Output parameters:  NONE
 *
 *  Return values:      NONE
 */
void console_outbyte_interrupts(
  const Port_85C30_info *Port,
  char ch
)
{
  Console_Protocol   *protocol;
  uint32_t            isrlevel;

  protocol = Port->Protocol;

  /*
   *  If this is the first character then we need to prime the pump
   */

  if ( protocol->Is_TX_active == false ) {

    rtems_interrupt_disable( isrlevel );
    protocol->Is_TX_active = true;
    outbyte_polled_85c30( Port->ctrl, ch );
    rtems_interrupt_enable( isrlevel );

    return;
  }

  while ( Ring_buffer_Is_full( &protocol->TX_Buffer ) );

  Ring_buffer_Add_character( &protocol->TX_Buffer, ch );
}

#endif

/* const char arg to be compatible with BSP_output_char decl. */
void
debug_putc_onlcr(const char c)
{
  int                      console;
  volatile uint8_t         *csr;
  uint32_t                 isrlevel;

  console = USE_FOR_CONSOLE;
  csr = Ports_85C30[ console ].ctrl;

  if ('\n'==c){
    rtems_interrupt_disable( isrlevel );
    outbyte_polled_85c30( csr, '\r' );
    __asm__ volatile("isync");
    rtems_interrupt_enable( isrlevel );
  }

  rtems_interrupt_disable( isrlevel );
  outbyte_polled_85c30( csr, c );
  __asm__ volatile("isync");
  rtems_interrupt_enable( isrlevel );
}

BSP_output_char_function_type     BSP_output_char = debug_putc_onlcr;
BSP_polling_getchar_function_type BSP_poll_char = NULL;
/* const char arg to be compatible with BSP_output_char decl. */