From b45952659c490c7ccebba3c7e05c8f271776c2ca Mon Sep 17 00:00:00 2001 From: Joel Sherrill Date: Wed, 30 Aug 2000 08:18:56 +0000 Subject: 2000-08-26 Rosimildo da Silva * shared/comm: Added "/dev/ttyS1" & "/dev/ttyS2" support for the i386 BSPs. * shared/comm/gdb_glue.c: New file. * shared/comm/i386_io.c: New file. * shared/comm/tty_drv.c: New file. * shared/comm/tty_drv.h: New file. * shared/comm/Makefile.am: Account for new files. * shared/comm/uart.c: Adds support for sending characters to another "line discipline." --- c/src/lib/libbsp/i386/shared/ChangeLog | 12 + c/src/lib/libbsp/i386/shared/comm/Makefile.am | 7 +- c/src/lib/libbsp/i386/shared/comm/gdb_glue.c | 63 ++++ c/src/lib/libbsp/i386/shared/comm/i386_io.h | 66 ++++ c/src/lib/libbsp/i386/shared/comm/tty_drv.c | 446 ++++++++++++++++++++++++++ c/src/lib/libbsp/i386/shared/comm/tty_drv.h | 107 ++++++ c/src/lib/libbsp/i386/shared/comm/uart.c | 45 ++- 7 files changed, 737 insertions(+), 9 deletions(-) create mode 100644 c/src/lib/libbsp/i386/shared/comm/gdb_glue.c create mode 100644 c/src/lib/libbsp/i386/shared/comm/i386_io.h create mode 100644 c/src/lib/libbsp/i386/shared/comm/tty_drv.c create mode 100644 c/src/lib/libbsp/i386/shared/comm/tty_drv.h (limited to 'c/src') diff --git a/c/src/lib/libbsp/i386/shared/ChangeLog b/c/src/lib/libbsp/i386/shared/ChangeLog index 33320a1444..e34ec34ae3 100644 --- a/c/src/lib/libbsp/i386/shared/ChangeLog +++ b/c/src/lib/libbsp/i386/shared/ChangeLog @@ -1,2 +1,14 @@ + * shared/comm: Added "/dev/ttyS1" & "/dev/ttyS2" support for + the i386 BSPs. + * shared/comm/gdb_glue.c: New file. + * shared/comm/i386_io.c: New file. + * shared/comm/tty_drv.c: New file. + * shared/comm/tty_drv.h: New file. + * shared/comm/Makefile.am: Account for new files. + * shared/comm/uart.c: Adds support for sending characters to + another "line discipline." + +2000-08-10 Joel Sherrill + * ChangeLog: New file. diff --git a/c/src/lib/libbsp/i386/shared/comm/Makefile.am b/c/src/lib/libbsp/i386/shared/comm/Makefile.am index 5db6da55a3..2fa090f145 100644 --- a/c/src/lib/libbsp/i386/shared/comm/Makefile.am +++ b/c/src/lib/libbsp/i386/shared/comm/Makefile.am @@ -4,9 +4,9 @@ AUTOMAKE_OPTIONS = foreign 1.4 -H_FILES = uart.h +H_FILES = uart.h tty_drv.h i386_io.h -C_FILES = i386-stub-glue.c i386-stub.c uart.c +C_FILES = i386-stub-glue.c i386-stub.c uart.c tty_drv.c gdb_glue.c noinst_DATA = GDB.HOWTO @@ -19,6 +19,7 @@ PREINSTALL_FILES += $(PROJECT_INCLUDE) $(H_FILES:%.h=$(PROJECT_INCLUDE)/%.h) all-local: $(PREINSTALL_FILES) -EXTRA_DIST = GDB.HOWTO i386-stub-glue.c i386-stub.c uart.c uart.h +EXTRA_DIST = GDB.HOWTO i386-stub-glue.c i386-stub.c uart.c uart.h tty_drv.h \ + i386_io.h tty_drv.c gdb_glue.c include $(top_srcdir)/../../../../../automake/local.am diff --git a/c/src/lib/libbsp/i386/shared/comm/gdb_glue.c b/c/src/lib/libbsp/i386/shared/comm/gdb_glue.c new file mode 100644 index 0000000000..3dced2d10f --- /dev/null +++ b/c/src/lib/libbsp/i386/shared/comm/gdb_glue.c @@ -0,0 +1,63 @@ +/* gdb_glue + * + * Interface to initialize the GDB. + * + * COPYRIGHT (c) 1989-1998. + * On-Line Applications Research Corporation (OAR). + * Copyright assigned to U.S. Government, 1994. + * + * 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$ + */ + +#include +#include +#include + +#define BREAKPOINT() asm(" int $3"); + +extern int BSPConsolePort; + + /* Init GDB glue */ +void init_remote_gdb( void ) +{ + if(BSPConsolePort != BSP_UART_COM2) + { + /* + * If com2 is not used as console use it for + * debugging + */ + + i386_stub_glue_init(BSP_UART_COM2); + printf( "Remote GDB using COM2...\n" ); + + } + else + { + /* Otherwise use com1 */ + i386_stub_glue_init(BSP_UART_COM1); + printf( "Remote GDB using COM1...\n" ); + } + + printf( "Remote GDB: setting traps...\n" ); + /* Init GDB stub itself */ + set_debug_traps(); + + + printf( "Remote GDB: waiting remote connection....\n" ); + + /* + * Init GDB break in capability, + * has to be called after + * set_debug_traps + */ + i386_stub_glue_init_breakin(); + + /* Put breakpoint in */ + /* breakpoint(); */ + /* BREAKPOINT(); */ +} + diff --git a/c/src/lib/libbsp/i386/shared/comm/i386_io.h b/c/src/lib/libbsp/i386/shared/comm/i386_io.h new file mode 100644 index 0000000000..e8137d33d1 --- /dev/null +++ b/c/src/lib/libbsp/i386/shared/comm/i386_io.h @@ -0,0 +1,66 @@ +/* +///////////////////////////////////////////////////////////////////////////// +// $Header$ +// +// Copyright (c) 2000 - Rosimildo da Silva. All Rights Reserved. +// +// MODULE DESCRIPTION: +// +// IO Functions for the PC platform equivalent to DOS/Linux. They make +// eaiser the porting of code from these platforms. +// +// by: Rosimildo da Silva: rdasilva@connecttel.com +// +// MODIFICATION/HISTORY: +// $Log$ +// +///////////////////////////////////////////////////////////////////////////// +*/ + +#ifndef i386_io_h__ +#define i386_io_h__ + +#define rtems_inb(port) \ +({ \ + register int _inb_result; \ + \ + asm volatile ("xorl %%eax,%%eax; inb %%dx,%%al" : \ + "=a" (_inb_result) : "d" (port)); \ + _inb_result; \ +}) + +#define rtems_inw(port) \ +({ \ + register int _inbw_result; \ + \ + asm volatile ("xorl %%eax,%%eax; inw %%dx,%%ax" : \ + "=a" (_inbw_result) : "d" (port)); \ + _inbw_result; \ +}) + +#define rtems_outb(port, data) \ + asm volatile ("outb %%al,%%dx" : : "a" (data), "d" (port)) + +#define rtems_outw(port, data) \ + asm volatile ("outw %%ax,%%dx" : : "a" (data), "d" (port)) + +#define outp(port, val) rtems_outb(port,val) +#define inp(port) rtems_inb(port) + +#define outb(val, port) rtems_outb(port,val) +#define inb(port) rtems_inb(port) + +#define outb_p(val, port) rtems_outb(port,val) +#define inb_p(port) rtems_inb(port) + +#define outportb(port,val) rtems_outb(port,val) +#define inportb(port) rtems_inb(port) + +#define outw(val, port) rtems_outw(port,val) +#define inw(port) rtems_inw(port) + +#define cli() __asm__ __volatile__("cli") +#define sti() __asm__ __volatile__("sti"); + +#endif /* i386_io_h__ */ + diff --git a/c/src/lib/libbsp/i386/shared/comm/tty_drv.c b/c/src/lib/libbsp/i386/shared/comm/tty_drv.c new file mode 100644 index 0000000000..b6f3947d4b --- /dev/null +++ b/c/src/lib/libbsp/i386/shared/comm/tty_drv.c @@ -0,0 +1,446 @@ +/*************************************************************************** + * + * $Header$ + * + * MODULE DESCRIPTION: + * This module implements the RTEMS drivers for the PC serial ports + * as /dev/ttyS1 for COM1 and /dev/ttyS2 as COM2. If one of the ports + * is used as the console, this driver would fail to initialize. + * + * This code was based on the console driver. It is based on the + * current termios framework. This is just a shell around the + * termios support. + * + * by: Rosimildo da Silva: + * rdasilva@connecttel.com + * http://www.connecttel.com + * + * MODIFICATION/HISTORY: + * + * $Log$ + ****************************************************************************/ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +int BSP_poll_read(int); + +/* Internal routines */ +static int tty1_conSetAttr( int minor, const struct termios *t); +static int tty2_conSetAttr( int minor, const struct termios *t); +static void isr_on(const rtems_irq_connect_data *); +static void isr_off(const rtems_irq_connect_data *); +static int isr_is_on(const rtems_irq_connect_data *); + + +extern BSP_polling_getchar_function_type BSP_poll_char; +extern int BSPConsolePort; +extern void rtems_set_waiting_id_comx( int port, rtems_id id, rtems_event_set event ); + + +/* + * Interrupt structure for tty1 + */ +static rtems_irq_connect_data tty1_isr_data = +{ + BSP_UART_COM1_IRQ, + BSP_uart_termios_isr_com1, + isr_on, + isr_off, + isr_is_on}; + +/* + * Interrupt structure for tty2 + */ +static rtems_irq_connect_data tty2_isr_data = +{ + BSP_UART_COM2_IRQ, + BSP_uart_termios_isr_com2, + isr_on, + isr_off, + isr_is_on}; + +static void +isr_on(const rtems_irq_connect_data *unused) +{ + return; +} + +static void +isr_off(const rtems_irq_connect_data *unused) +{ + return; +} + +static int +isr_is_on(const rtems_irq_connect_data *irq) +{ + return BSP_irq_enabled_at_i8259s(irq->name); +} + +void tty_reserve_resources(rtems_configuration_table *conf) +{ + rtems_termios_reserve_resources(conf, 1); + return; +} + +/* + * TTYS1 - device driver INITIALIZE entry point. + */ +rtems_device_driver +tty1_initialize(rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg) +{ + rtems_status_code status; + + /* Check if this port is not been used as console */ + if( BSPConsolePort == BSP_UART_COM1 ) + { + status = -1; + printk("TTYS1: port selected as console.\n"); + rtems_fatal_error_occurred( status ); + } + + /* + * Set up TERMIOS + */ + rtems_termios_initialize(); + + /* + * Do device-specific initialization + */ + /* 9600-8-N-1, without hardware flow control */ + BSP_uart_init( BSP_UART_COM1, 9600, 0 ); + status = BSP_install_rtems_irq_handler( &tty1_isr_data ); + if( !status ) + { + printk("Error installing ttyS1 interrupt handler!\n"); + rtems_fatal_error_occurred(status); + } + /* + * Register the device + */ + status = rtems_io_register_name ("/dev/ttyS1", major, 0); + if (status != RTEMS_SUCCESSFUL) + { + printk("Error registering ttyS1 device!\n"); + rtems_fatal_error_occurred (status); + } + printk("Device: /dev/ttyS1 initialized.\n"); + return RTEMS_SUCCESSFUL; +} /* tty_initialize */ + + +static int tty1_last_close(int major, int minor, void *arg) +{ + BSP_remove_rtems_irq_handler( &tty1_isr_data ); + return 0; +} + +/* + * TTY1 - device driver OPEN entry point + */ +rtems_device_driver +tty1_open(rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg) +{ + rtems_status_code status; + static rtems_termios_callbacks cb = + { + NULL, /* firstOpen */ + tty1_last_close, /* lastClose */ + NULL, /* poll read */ + BSP_uart_termios_write_com1, /* write */ + tty1_conSetAttr, /* setAttributes */ + NULL, /* stopRemoteTx */ + NULL, /* startRemoteTx */ + 1 /* outputUsesInterrupts */ + }; + + status = rtems_termios_open( major, minor, arg, &cb ); + if(status != RTEMS_SUCCESSFUL) + { + printk("Error openning tty1 device\n"); + return status; + } + + /* + * Pass data area info down to driver + */ + BSP_uart_termios_set( BSP_UART_COM1, + ((rtems_libio_open_close_args_t *)arg)->iop->data1 ); + /* Enable interrupts on channel */ + BSP_uart_intr_ctrl( BSP_UART_COM1, BSP_UART_INTR_CTRL_TERMIOS); + return RTEMS_SUCCESSFUL; +} + +/* + * TTY - device driver CLOSE entry point + */ +rtems_device_driver +tty_close(rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg) +{ + + return (rtems_termios_close (arg)); + +} /* tty_close */ + + +/* + * TTY device driver READ entry point. + * Read characters from the tty device. + */ +rtems_device_driver +tty_read(rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg) +{ + return rtems_termios_read (arg); +} /* tty_read */ + + +/* + * TTY device driver WRITE entry point. + * Write characters to the tty device. + */ +rtems_device_driver +tty_write(rtems_device_major_number major, + rtems_device_minor_number minor, + void * arg) +{ + return rtems_termios_write (arg); + +} /* tty_write */ + +/* + * Handle ioctl request. This is a generic internal + * routine to handle both devices. + */ +static rtems_device_driver tty_control( int port, void *arg ) +{ + rtems_libio_ioctl_args_t *args = arg; + switch( args->command ) + { + default: + return rtems_termios_ioctl (arg); + break; + } + args->ioctl_return = 0; + return RTEMS_SUCCESSFUL; +} + + + +/* + * Handle ioctl request for ttyS1. + */ +rtems_device_driver +tty1_control(rtems_device_major_number major, + rtems_device_minor_number minor, + void * arg +) +{ + return tty_control( BSP_UART_COM1, arg ); +} + + +static int +conSetAttr(int port, int minor, const struct termios *t) +{ + int baud; + + switch (t->c_cflag & CBAUD) + { + case B50: + baud = 50; + break; + case B75: + baud = 75; + break; + case B110: + baud = 110; + break; + case B134: + baud = 134; + break; + case B150: + baud = 150; + break; + case B200: + baud = 200; + break; + case B300: + baud = 300; + break; + case B600: + baud = 600; + break; + case B1200: + baud = 1200; + break; + case B1800: + baud = 1800; + break; + case B2400: + baud = 2400; + break; + case B4800: + baud = 4800; + break; + case B9600: + baud = 9600; + break; + case B19200: + baud = 19200; + break; + case B38400: + baud = 38400; + break; + case B57600: + baud = 57600; + break; + case B115200: + baud = 115200; + break; + default: + baud = 0; + rtems_fatal_error_occurred (RTEMS_INTERNAL_ERROR); + return 0; + } + printk("Setting baud, port=%X, baud=%d\n", port, baud ); + BSP_uart_set_baud( port, baud ); + return 0; +} + +/* + * Handle ioctl request for ttyS2. + */ +static int +tty1_conSetAttr( int minor, const struct termios *t) +{ + return conSetAttr( BSP_UART_COM1, minor, t ); +} + + + +/* + * TTY2 device driver INITIALIZE entry point. + */ +rtems_device_driver +tty2_initialize(rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg) +{ + rtems_status_code status; + + /* Check if this port is not been used as console */ + if( BSPConsolePort == BSP_UART_COM2 ) + { + status = -1; + printk("TTY2: port selected as console.\n"); + rtems_fatal_error_occurred( status ); + } + + /* + * Set up TERMIOS + */ + rtems_termios_initialize(); + + /* + * Do device-specific initialization + */ + /* 9600-8-N-1, without hardware flow control */ + BSP_uart_init( BSP_UART_COM2, 9600, 0); + status = BSP_install_rtems_irq_handler( &tty2_isr_data ); + if( !status ) + { + printk("Error installing serial console interrupt handler!\n"); + rtems_fatal_error_occurred(status); + } + /* + * Register the device + */ + status = rtems_io_register_name ("/dev/ttyS2", major, 0); + if (status != RTEMS_SUCCESSFUL) + { + printk("Error registering tty2 device!\n"); + rtems_fatal_error_occurred (status); + } + printk("Device: /dev/ttyS2 initialized.\n"); + return RTEMS_SUCCESSFUL; +} /* tty_initialize */ + + +static int tty2_last_close(int major, int minor, void *arg) +{ + BSP_remove_rtems_irq_handler( &tty2_isr_data ); + return 0; +} + +/* + * TTY2 device driver OPEN entry point + */ +rtems_device_driver +tty2_open(rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg) +{ + rtems_status_code status; + static rtems_termios_callbacks cb = + { + NULL, /* firstOpen */ + tty2_last_close, /* lastClose */ + NULL, /* poll read */ + BSP_uart_termios_write_com2, /* write */ + tty2_conSetAttr, /* setAttributes */ + NULL, /* stopRemoteTx */ + NULL, /* startRemoteTx */ + 1 /* outputUsesInterrupts */ + }; + + status = rtems_termios_open (major, minor, arg, &cb); + if(status != RTEMS_SUCCESSFUL) + { + printk("Error openning tty1 device\n"); + return status; + } + + /* + * Pass data area info down to driver + */ + BSP_uart_termios_set( BSP_UART_COM2, + ((rtems_libio_open_close_args_t *)arg)->iop->data1 ); + /* Enable interrupts on channel */ + BSP_uart_intr_ctrl( BSP_UART_COM2, BSP_UART_INTR_CTRL_TERMIOS); + return RTEMS_SUCCESSFUL; +} + +/* + * Handle ioctl request for TTY2 + */ +rtems_device_driver +tty2_control(rtems_device_major_number major, + rtems_device_minor_number minor, + void * arg +) +{ + return tty_control( BSP_UART_COM2, arg ); +} + +static int +tty2_conSetAttr( int minor, const struct termios *t) +{ + return conSetAttr( BSP_UART_COM2, minor, t ); +} diff --git a/c/src/lib/libbsp/i386/shared/comm/tty_drv.h b/c/src/lib/libbsp/i386/shared/comm/tty_drv.h new file mode 100644 index 0000000000..c4c1be23f0 --- /dev/null +++ b/c/src/lib/libbsp/i386/shared/comm/tty_drv.h @@ -0,0 +1,107 @@ +#ifndef __tty_drv__ +#define __tty_drv__ +/*************************************************************************** + * + * $Header$ + * + * Copyright (c) 1999 ConnectTel, Inc. All Rights Reserved. + * + * MODULE DESCRIPTION: Prototype routines for the ttySx driver. + * + * by: Rosimildo da Silva: + * rdasilva@connecttel.com + * http://www.connecttel.com + * + * MODIFICATION/HISTORY: + * + * $Log$ + ****************************************************************************/ + +/* functions */ +#ifdef __cplusplus +extern "C" { +#endif + + +/* ttyS1 entry points */ +rtems_device_driver tty1_initialize( + rtems_device_major_number, + rtems_device_minor_number, + void * +); + +rtems_device_driver tty1_open( + rtems_device_major_number, + rtems_device_minor_number, + void * +); + +rtems_device_driver tty1_control( + rtems_device_major_number, + rtems_device_minor_number, + void * +); + + +/* tty1 & tty2 shared entry points */ +rtems_device_driver tty_close( + rtems_device_major_number, + rtems_device_minor_number, + void * +); + + +rtems_device_driver tty_read( + rtems_device_major_number, + rtems_device_minor_number, + void * +); + +rtems_device_driver tty_write( + rtems_device_major_number, + rtems_device_minor_number, + void * +); + + + +/* tty2 entry points */ +rtems_device_driver tty2_initialize( + rtems_device_major_number, + rtems_device_minor_number, + void * +); + +rtems_device_driver tty2_open( + rtems_device_major_number, + rtems_device_minor_number, + void * +); + +rtems_device_driver tty2_control( + rtems_device_major_number, + rtems_device_minor_number, + void * +); + + + +#define TTY1_DRIVER_TABLE_ENTRY \ + { tty1_initialize, tty1_open, tty_close, \ + tty_read, tty_write, tty1_control } + + +#define TTY2_DRIVER_TABLE_ENTRY \ + { tty2_initialize, tty2_open, tty_close, \ + tty_read, tty_write, tty2_control } + + + +#ifdef __cplusplus +} +#endif +/* end of include file */ + +#endif /* __tty_drv__ */ + + diff --git a/c/src/lib/libbsp/i386/shared/comm/uart.c b/c/src/lib/libbsp/i386/shared/comm/uart.c index b55be1a01e..c794e922a3 100644 --- a/c/src/lib/libbsp/i386/shared/comm/uart.c +++ b/c/src/lib/libbsp/i386/shared/comm/uart.c @@ -424,6 +424,28 @@ static void* termios_ttyp_com2 = NULL; static char termios_tx_hold_com2 = 0; static volatile char termios_tx_hold_valid_com2 = 0; +static void ( *driver_input_handler_com1 )( void *, char *, int ) = 0; +static void ( *driver_input_handler_com2 )( void *, char *, int ) = 0; + +/* + * This routine sets the handler to handle the characters received + * from the serial port. + */ +void uart_set_driver_handler( int port, void ( *handler )( void *, char *, int ) ) +{ + switch( port ) + { + case BSP_UART_COM1: + driver_input_handler_com1 = handler; + break; + + case BSP_UART_COM2: + driver_input_handler_com2 = handler; + break; + } +} + + /* * Set channel parameters */ @@ -616,9 +638,15 @@ BSP_uart_termios_isr_com1(void) if(off != 0) { /* Update rx buffer */ - rtems_termios_enqueue_raw_characters(termios_ttyp_com1, - (char *)buf, - off); + if( driver_input_handler_com1 ) + { + driver_input_handler_com1( termios_ttyp_com1, (char *)buf, off ); + } + else + { + /* Update rx buffer */ + rtems_termios_enqueue_raw_characters(termios_ttyp_com1, (char *)buf, off ); + } } return; case TRANSMITTER_HODING_REGISTER_EMPTY : @@ -710,9 +738,14 @@ BSP_uart_termios_isr_com2() if(off != 0) { /* Update rx buffer */ - rtems_termios_enqueue_raw_characters(termios_ttyp_com2, - (char *)buf, - off); + if( driver_input_handler_com2 ) + { + driver_input_handler_com2( termios_ttyp_com2, (char *)buf, off ); + } + else + { + rtems_termios_enqueue_raw_characters(termios_ttyp_com2, (char *)buf, off); + } } return; case TRANSMITTER_HODING_REGISTER_EMPTY : -- cgit v1.2.3