From 486c329f2b4f95dbfefdcbefbe6b25adf7895a94 Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Wed, 20 Sep 1995 15:05:19 +0000 Subject: Actually adding efi bsp's from John Gwynne after forgetting to commit them. --- c/src/lib/libbsp/m68k/efi332/console/console.c | 390 +++++++++++++++++++++++++ 1 file changed, 390 insertions(+) create mode 100644 c/src/lib/libbsp/m68k/efi332/console/console.c (limited to 'c/src/lib/libbsp/m68k/efi332/console/console.c') diff --git a/c/src/lib/libbsp/m68k/efi332/console/console.c b/c/src/lib/libbsp/m68k/efi332/console/console.c new file mode 100644 index 0000000000..b16ec72334 --- /dev/null +++ b/c/src/lib/libbsp/m68k/efi332/console/console.c @@ -0,0 +1,390 @@ +/* + * This file contains the efi332 console IO package. + * + * COPYRIGHT (c) 1989, 1990, 1991, 1992, 1993, 1994. + * On-Line Applications Research Corporation (OAR). + * All rights assigned to U.S. Government, 1994. + * + * This material may be reproduced by or for the U.S. Government pursuant + * to the copyright license under the clause at DFARS 252.227-7013. This + * notice must appear in all copies of this file and its derivatives. + * + * $Id$ + */ + +#include +#include +#include + +/* 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: + */ + +rtems_device_driver console_initialize( + rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg +) +{ + rtems_status_code status; + + *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); + 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 = 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'; + buffer[ count ] = 0; + 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; +} + -- cgit v1.2.3