diff options
Diffstat (limited to 'c/src/lib/libbsp/or32/orp/console/console.c')
-rw-r--r-- | c/src/lib/libbsp/or32/orp/console/console.c | 377 |
1 files changed, 377 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/or32/orp/console/console.c b/c/src/lib/libbsp/or32/orp/console/console.c new file mode 100644 index 0000000000..a5081c1b50 --- /dev/null +++ b/c/src/lib/libbsp/or32/orp/console/console.c @@ -0,0 +1,377 @@ +/* + * This file contains the template for a 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. + * + * This file adapted from no_bsp board library of the RTEMS distribution. + * The body has been modified for the Bender Or1k implementation by + * Chris Ziomkowski. <chris@asics.ws> + */ + +#define BENDER_INIT + +#include <bsp.h> +#include <rtems/libio.h> +#include "console.h" + +static int localEcho; +static UART_16450* uart = (UART_16450*)0x80000000; /* This is where the simulator puts it */ + +/* console_initialize + * + * This routine initializes the console IO driver. + * + * Input parameters: NONE + * + * Output parameters: NONE + * + * Return values: + */ + +void (*old_handler)(unsigned int,unsigned int,unsigned int,unsigned int); + +void console_interrupt(unsigned int vector,unsigned int pc, + unsigned int effective_addr, unsigned int status) +{ + int reason; + register int pending; + + /* First thing's first...is this for us? */ + asm volatile ("l.mfspr %0,r0,0x4802 \n\t" /* Read the PIC status */ + "l.andi %0,%0,0x4 \n\t" : "=r" (pending)); + + if(pending) + { + reason = uart->read.IIR; + + switch(reason) + { + case 0: /* Interrupt because of modem status */ + break; + case 2: /* Interrupt because Transmitter empty */ + break; + case 4: /* Interrupt because Received data available */ + break; + case 6: /* Interrupt because Status Register */ + break; + case 12: /* Interrupt because of character timeout (16550 only) */ + break; + default: /* No interrupt */ + break; + } + } + + if(old_handler) + (*old_handler)(vector,pc,effective_addr,status); +} + +rtems_device_driver console_initialize( + rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg +) +{ + rtems_status_code status; + int tmp,tmp2; + unsigned32 sr; + extern unsigned32 Or1k_Interrupt_Vectors[16]; + + /* Make sure the UART (interrupt 2) is enabled and + reports a low prority interrupt */ + asm volatile ("l.mfspr %0,r0,0x4800 \n\t" /* Get the PIC mask */ + "l.ori %0,%0,0x4 \n\t" /* Enable int 2 */ + "l.mtspr r0,%0,0x4800 \n\t" /* Write back mask */ + "l.mfspr %0,r0,0x4801 \n\t" /* Get priority mask */ + "l.addi %1,r0,-5 \n\t" + "l.and %0,%0,%1 \n\t" /* Set us to low */ + "l.mtspr r0,%0,0x4801 \n\t" /* Write back to PICPR */ + : "=r" (tmp), "=r" (tmp2)); + + /* Install the interrupt handler */ + asm volatile ("l.mfspr %0,r0,0x11 \n\t" + "l.addi %1,r0,-5 \n\t" + "l.and %1,%1,%0 \n\t" + "l.mtspr r0,%1,0x11 \n\t": "=&r" (sr) : "r" (tmp)); + + old_handler = (void(*)(unsigned int,unsigned int,unsigned int,unsigned int)) + Or1k_Interrupt_Vectors[5]; + Or1k_Interrupt_Vectors[5] = (unsigned32)console_interrupt; + + asm volatile ("l.mtspr r0,%0,0x11\n\t":: "r" (sr)); + + /* Assume 1843.2/16 kHz clock */ + uart->latch.LCR = 0x80; /* Set the divisor latch bit */ + uart->latch.DLM = 2; /* 57,600 */ + uart->latch.DLL = 0; + uart->write.LCR = 0x03; /* 8-N-1 */ + uart->write.MCR = 0x03; /* Assert RTS & DTR */ + /* uart->write.FCR = 0x00; */ /* Make sure we're in 16450 mode... Ignore for 16450 driver */ + uart->write.IER = 0x05; /* Don't worry about TEMT unless we need to. */ + + tmp = uart->read.LSR; /* Make sure interrupts are cleared */ + tmp = uart->read.RBR; /* Clear the input buffer */ + tmp = uart->read.MSR; /* Clear the modem status register */ + + localEcho = 1; /* Turn on local echo */ + + 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 +) +{ + *ch = '\0'; /* return NULL for no particular reason */ + return(TRUE); +} + +/* inbyte + * + * This routine reads a character from the SOURCE. + * + * Input parameters: NONE + * + * Output parameters: NONE + * + * Return values: + * character read from SOURCE + */ + +char inbyte( void ) +{ + unsigned int stat; + + stat = uart->read.LSR; + while(!(stat & 0x01)) /* ! Data Ready */ + { + rtems_task_wake_after( RTEMS_YIELD_PROCESSOR ); + stat = uart->read.LSR; + } + + return uart->read.RBR; /* Return the character */ +} + +/* outbyte + * + * This routine transmits a character out the SOURCE. Flow + * control is not currently enabled. + * + * Input parameters: + * ch - character to be transmitted + * + * Output parameters: NONE + */ + +void outbyte(char ch) +{ + unsigned int stat; + /* + * Carriage Return/New line translation. + */ + + stat = uart->read.LSR; + while(!(stat & 0x40)) /* ! TEMT */ + { + rtems_task_wake_after( RTEMS_YIELD_PROCESSOR ); + stat = uart->read.LSR; + } + + uart->write.THR = ch; + if ( ch == '\n' ) + outbyte( '\r' ); +} + + +/* + * 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 = 0; + + 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'; + if(localEcho) + outbyte('\n' ); /* newline */ + break; /* Return for a newline */ + } + else if (buffer[ count ] == '\b' && count > 0 ) + { + if(localEcho) + { + outbyte('\b' ); /* move back one space */ + outbyte(' ' ); /* erase the character */ + outbyte('\b' ); /* move back one space */ + } + count-=2; + } + else if(localEcho) + outbyte(buffer[ count ]); /* echo the character */ + } + + 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 +) +{ + int param,div; + ConsoleIOCTLRequest* request = (ConsoleIOCTLRequest*)arg; + + if (!arg) + return RTEMS_INVALID_ADDRESS; + + switch(request->command) + { + case TERM_LOCAL_ECHO: + param = (int)(request->data); + if(param < 0 || param > 1) + return RTEMS_INVALID_NUMBER; + localEcho = param; + break; + case TERM_BIT_RATE: + param = (int)(request->data); + switch(param) + { + case 50: + case 150: + case 300: + case 600: + case 1200: + case 1800: + case 2000: + case 2400: + case 3600: + case 4800: + case 7200: + case 9600: + case 19200: + case 38400: + case 57600: + case 115200: + div = 115200/param; + uart->latch.LCR |= 0x80; /* Set the divisor latch bit */ + uart->latch.DLM = div & 0xFF; + uart->latch.DLL = div >> 8; + uart->write.LCR &= 0x7F; /* Clear the divisor latch bit */ + break; + default: + return RTEMS_INVALID_NUMBER; + } + break; + default: + return RTEMS_NOT_CONFIGURED; + } + + return RTEMS_SUCCESSFUL; +} |