OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [rtems/] [c/] [src/] [lib/] [libbsp/] [m68k/] [efi332/] [console/] [console.c] - Rev 562

Go to most recent revision | Compare with Previous | Blame | View Log

/*
 *  This file contains the efi332 console IO package.
 *
 *  COPYRIGHT (c) 1989-1999.
 *  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.OARcorp.com/rtems/license.html.
 *
 *  $Id: console.c,v 1.2 2001-09-27 12:00:01 chris Exp $
 */
 
#include <stdlib.h>
#include <bsp.h>
#include <rtems/libio.h>
 
/* BUFFER_LENGTH must be 2^n for n=1, 2, 3, .... */
#define BUFFER_LENGTH 256
#define RTS_STOP_SIZE BUFFER_LENGTH-64
#define RTS_START_SIZE 16
 
char xmt_buf[BUFFER_LENGTH];
char rcv_buf[BUFFER_LENGTH];
/* in: last entry into the buffer; always on a valid character */
/* out: points to the next character to be pull from the buffer */
/*    in+1=out => buffer empty */
/*    in+2=out => buffer full */
struct UART_buf {
  char *offset; 
  char *in; 
  char *out;
};
static volatile struct UART_buf  xmt = { xmt_buf, (char *)0, (char *)1};
static volatile struct UART_buf  rcv = { rcv_buf, (char *)0, (char *)1};
static volatile char _debug_flag = 0;
 
#define SET_RTS(a) {*PORTF0 = (*PORTF0 & ~0x4) | ( (a)? 0 : 0x4); }
#define GET_CTS (!(*PORTF0 & 0x2))
 
/* _catchSCIint, _catchCTSint, and _catchSPURIOUSint are the 
   interrupt front-ends */
extern void _catchSCIint();
asm("   .text
        .align 2
        .globl _catchSCIint
_catchSCIint:
        moveml %d0-%d7/%a0-%a6,%sp@-       /* save registers */
        jbsr    uart_interrupt
        moveml  %sp@+,%d0-%d7/%a0-%a6			        
        rte
    ");
 
extern void _catchCTSint();
asm("   .text
        .align 2
        .globl _catchCTSint
_catchCTSint:
        moveml %d0-%d7/%a0-%a6,%sp@-       /* save registers */
        jbsr    cts_interrupt
        moveml  %sp@+,%d0-%d7/%a0-%a6			        
        rte
    ");
 
extern void _catchSPURIOUSint();
asm("   .text
        .align 2
        .globl _catchSPURIOUSint
_catchSPURIOUSint:
        moveml %d0-%d7/%a0-%a6,%sp@-       /* save registers */
        jbsr    spurious_interrupt
        moveml  %sp@+,%d0-%d7/%a0-%a6			        
        rte
    ");
 
int _spurious_int_counter=0;
 
/* note: cts uses int1. If it "bounces", a spurious interrupt is generated */
void spurious_interrupt(void) {
  _spurious_int_counter++;	/* there should never be alot of these */
}
 
/* _fake_trap_1 will continue the UART interrupt (%sr *still*
   UART_ISR_LEVEL) as a trap #1 to enter the debugger */
 
/* *****fix me; this is for 68000 w/jsr ram exception table ******* */
asm("   .text
        .align 2
_fake_trap_1:
        unlk %a6		/* clear interrupt frame */
        lea %sp@(4),%sp		/* remove jbsr instruction */
        moveml %sp@+,%d0-%d7/%a0-%a6 /* pop registers */
        jmp (33*6-12)	/* jump exception 1 */
        ");
 
/* dispatch UART interrupt */
void xmit_interrupt(void);
void rcvr_interrupt(void);
void _fake_trap_1(void);
 
void uart_interrupt(void) {
  /* receiver status bits are cleared by a SCSR read followed 
     by a SCDR read. transmitter status bits are cleared by
     a SCSR read followed by a SCDR write. */
  if ((*SCSR) & (TDRE | TC))
    xmit_interrupt();
 
  if ((*SCSR) & (RDRF))
    rcvr_interrupt();
 
  if (_debug_flag) {
    _debug_flag = 0;		/* reset the flag */
    _fake_trap_1();		/* fake a trap #1 */
  }
}
 
/* transfer received character to the buffer */
void rcvr_interrupt(void) {
  register char *a, c;
  register int length;
 
  while((*SCSR) & (RDRF)) {
    if ((c=*SCDR) == 0x1a) 	/* use ctl-z to reboot */
      reboot();
/*     else if (c == 0x03) { */	/* use ctl-c to enter debugger */
/*       _debug_flag = 1; */
/*       continue; */
/*     } */
 
    *(char *)((int)rcv.offset +(int)
	      (a=(char *)(((int)rcv.in+1) & ((int)BUFFER_LENGTH-1)))) = c;
    if ((char *)(((int)rcv.in+2) & ((int)BUFFER_LENGTH-1)) != rcv.out)
      rcv.in=a;
  };
 
  length = (BUFFER_LENGTH -1) & ( 
    ( ((int)rcv.out <= (int)rcv.in) ? 0 : BUFFER_LENGTH) - (int)rcv.out 
    + (int)rcv.in + 1);
  if (length >= RTS_STOP_SIZE)
    SET_RTS(0);
}
 
/* tranfer buffered characters to the UART */
void xmit_interrupt(void) {
  register short int oldsr;
 
  _CPU_ISR_Disable( oldsr ); /* for when outbyte or flush calls */
  while ((*SCSR) & (TDRE)) {
    if ((char *)(((int)xmt.in+1) & ((int)BUFFER_LENGTH-1)) != xmt.out)
      /* xmit buffer not empty */
      if (GET_CTS) {
	/* send next char */
	*SCDR=*(char *)((int)xmt.offset+(int)xmt.out);
	xmt.out= (char *)(((int)xmt.out+1) & ((int)BUFFER_LENGTH-1));
	*SCCR1 = (*SCCR1 & ~(TIE | TCIE)) | (TIE);
      } 
      else {
	/* configue CTS interrupt and shutdown xmit interrupts */
	*SCCR1 &= ~(TIE | TCIE);
	*PFPAR |= 0x2;
	break;
      }
    else {
      /* xmit buffer empty; shutdown interrupts */
      *SCCR1 &= ~(TIE | TCIE);
      break;
    }
  }
  _CPU_ISR_Enable( oldsr );
}
 
void cts_interrupt(void) {
  register short int oldsr;
 
  _CPU_ISR_Disable( oldsr ); /* for when outbyte calls */
 
  *PFPAR &= ~0x2;
  *SCCR1 = (*SCCR1 & ~(TIE | TCIE)) | (TIE);
 
  _CPU_ISR_Enable( oldsr );
}
 
 
 
/* transfer character from the buffer */
char inbyte(void) {
  register char a;
  register int length;
 
  while ((char *)(((int)rcv.in+1) & ((int)BUFFER_LENGTH-1))== rcv.out);
  a=*(char *)((int)rcv.offset+(int)rcv.out);
  rcv.out= (char *)(((int)rcv.out+1) & ((int)BUFFER_LENGTH-1));
  length = (BUFFER_LENGTH -1) & ( 
    ( ((int)rcv.out <= (int)rcv.in) ? 0 : BUFFER_LENGTH) - (int)rcv.out 
    + (int)rcv.in + 1);
  if (length < RTS_START_SIZE)
    SET_RTS(1);
  return (a);
}
 
/* once room is avaliable in the buffer, transfer
   the character into the buffer and enable 
   the xmtr interrupt */
void outbyte(char c) {
  register char *a;
 
  while ((char *)(((int)xmt.in+2) & ((int)BUFFER_LENGTH-1)) == xmt.out);
  *(char *)((int)xmt.offset+(int)
	    (a=(char *)(((int)xmt.in+1) & ((int)BUFFER_LENGTH-1))))=c;
  xmt.in=a;
 
  if (!(*SCCR1 & (TIE | TCIE)) && (!(*PFPAR & 0x2)) )
                                /* if neither interrupts are running, */
    xmit_interrupt();		/*    we need to restart the xmiter */
}
 
void _UART_flush(void) {
  /* loop till xmt buffer empty. Works with interrupts disabled */
  while ((char *)(((int)xmt.in+1) & ((int)BUFFER_LENGTH-1)) != xmt.out)
    xmit_interrupt();
  /* loop till UART buffer empty */
  while ( (*SCSR & TC) == 0 );
}
 
/*  console_initialize
 *
 *  This routine initializes the console IO driver.
 *
 *  Input parameters: NONE
 *
 *  Output parameters:  NONE
 *
 *  Return values:
 */
 
void console_init()
{
  *QSMCR = ( SAM(QSM_IARB,0,IARB) );
  *QILR = ( SAM(ISRL_QSPI,4,ILQSPI) | SAM(ISRL_SCI,0,ILSCI) );
  *QIVR = ( SAM(EFI_QIVR,0,INTV) );
 
  *SCCR0 = ( (int)( SYS_CLOCK/SCI_BAUD/32.0+0.5 ) & 0x1fff );
  *SCCR1 = ( RIE | TE | RE );
 
  set_vector(_catchSPURIOUSint, EFI_SPINT, 0);
  set_vector(_catchSCIint, EFI_QIVR, 0);
  set_vector(_catchCTSint, EFI_INT1, 0);
}
 
rtems_device_driver console_initialize(
  rtems_device_major_number  major,
  rtems_device_minor_number  minor,
  void                      *arg
)
{
  rtems_status_code status;
 
  status = rtems_io_register_name(
    "/dev/console",
    major,
    (rtems_device_minor_number) 0
  );
 
  if (status != RTEMS_SUCCESSFUL)
    rtems_fatal_error_occurred(status);
 
  return RTEMS_SUCCESSFUL;
}
 
/*  is_character_ready
 *
 *  This routine returns TRUE if a character is available.
 *
 *  Input parameters: NONE
 *
 *  Output parameters:  NONE
 *
 *  Return values:
 */
 
rtems_boolean is_character_ready(
  char *ch
)
{
  if ((char *)(((int)rcv.in+1) & ((int)BUFFER_LENGTH-1))== rcv.out)
    return(FALSE);
  else
    return(TRUE);
}
 
/*
 *  Open entry point
 */
 
rtems_device_driver console_open(
  rtems_device_major_number major,
  rtems_device_minor_number minor,
  void                    * arg
)
{
  return RTEMS_SUCCESSFUL;
}
 
/*
 *  Close entry point
 */
 
rtems_device_driver console_close(
  rtems_device_major_number major,
  rtems_device_minor_number minor,
  void                    * arg
)
{
  return RTEMS_SUCCESSFUL;
}
 
/*
 * read bytes from the serial port. We only have stdin.
 */
 
rtems_device_driver console_read(
  rtems_device_major_number major,
  rtems_device_minor_number minor,
  void                    * arg
)
{
  rtems_libio_rw_args_t *rw_args;
  char *buffer;
  int maximum;
  int count;
 
  rw_args = (rtems_libio_rw_args_t *) arg;
 
  buffer = rw_args->buffer;
  maximum = rw_args->count;
 
  for (count = 0; count < maximum; count++) {
    buffer[ count ] = inbyte();
    if (buffer[ count ] == '\n' || buffer[ count ] == '\r') {
      buffer[ count++ ]  = '\n';
      break;
    }
  }
 
  rw_args->bytes_moved = count;
  return (count >= 0) ? RTEMS_SUCCESSFUL : RTEMS_UNSATISFIED;
}
 
/*
 * write bytes to the serial port. Stdout and stderr are the same.
 */
 
rtems_device_driver console_write(
  rtems_device_major_number major,
  rtems_device_minor_number minor,
  void                    * arg
)
{
  int count;
  int maximum;
  rtems_libio_rw_args_t *rw_args;
  char *buffer;
 
  rw_args = (rtems_libio_rw_args_t *) arg;
 
  buffer = rw_args->buffer;
  maximum = rw_args->count;
 
  for (count = 0; count < maximum; count++) {
    if ( buffer[ count ] == '\n') {
      outbyte('\r');
    }
    outbyte( buffer[ count ] );
  }
 
  rw_args->bytes_moved = maximum;
  return 0;
}
 
/*
 *  IO Control entry point
 */
 
rtems_device_driver console_control(
  rtems_device_major_number major,
  rtems_device_minor_number minor,
  void                    * arg
)
{
  return RTEMS_SUCCESSFUL;
}
 
 

Go to most recent revision | Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.