2000-08-26 Rosimildo da Silva <rdasilva@connecttel.com>

* 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."
This commit is contained in:
Joel Sherrill
2000-08-30 08:18:56 +00:00
parent 3cbb63ac77
commit b45952659c
7 changed files with 737 additions and 9 deletions

View File

@@ -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 <joel@OARcorp.com>
* ChangeLog: New file.

View File

@@ -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

View File

@@ -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 <bsp.h>
#include <stdio.h>
#include <uart.h>
#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(); */
}

View File

@@ -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__ */

View File

@@ -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 <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <bsp.h>
#include <irq.h>
#include <rtems/libio.h>
#include <termios.h>
#include <uart.h>
#include <libcpu/cpuModel.h>
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 );
}

View File

@@ -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__ */

View File

@@ -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 :