diff options
Diffstat (limited to '')
31 files changed, 3515 insertions, 376 deletions
diff --git a/c/src/lib/libbsp/i386/i386ex/clock/ckinit.c b/c/src/lib/libbsp/i386/i386ex/clock/ckinit.c index 6259b2d423..091d6fab45 100644 --- a/c/src/lib/libbsp/i386/i386ex/clock/ckinit.c +++ b/c/src/lib/libbsp/i386/i386ex/clock/ckinit.c @@ -77,7 +77,7 @@ int ClockIsOn(const rtems_irq_connect_data* unused) return ((i8259s_cache & 0x1) == 0); } -static rtems_irq_connect_data clockIrqData = {PC_386_PERIODIC_TIMER, +static rtems_irq_connect_data clockIrqData = {BSP_PERIODIC_TIMER, Clock_isr, ClockOn, ClockOff, @@ -114,7 +114,7 @@ rtems_device_driver Clock_initialize( outport_byte ( TMR0 , clock_lsb ); /* load LSB first */ outport_byte ( TMR0 , clock_msb ); /* then MSB */ - if (!pc386_install_rtems_irq_handler (&clockIrqData)) { + if (!BSP_install_rtems_irq_handler (&clockIrqData)) { printk("Unable to initialize system clock\n"); rtems_fatal_error_occurred(1); } @@ -151,7 +151,7 @@ rtems_device_driver Clock_control( } else if (args->command == rtems_build_name('N', 'E', 'W', ' ')) { - if (!pc386_install_rtems_irq_handler (&clockIrqData)) { + if (!BSP_install_rtems_irq_handler (&clockIrqData)) { printk("Error installing clock interrupt handler!\n"); rtems_fatal_error_occurred(1); } @@ -168,5 +168,5 @@ done: void Clock_exit() { ClockOff(&clockIrqData); - pc386_remove_rtems_irq_handler (&clockIrqData); + BSP_remove_rtems_irq_handler (&clockIrqData); } diff --git a/c/src/lib/libbsp/i386/i386ex/console/console.c b/c/src/lib/libbsp/i386/i386ex/console/console.c index c535d7efad..84458d5028 100644 --- a/c/src/lib/libbsp/i386/i386ex/console/console.c +++ b/c/src/lib/libbsp/i386/i386ex/console/console.c @@ -1,295 +1,401 @@ -/* - * This file contains the i386ex console IO package. - * - * 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$ - */ +/*-------------------------------------------------------------------------+ +| console.c v1.1 - i386ex BSP - 1997/08/07 ++--------------------------------------------------------------------------+ +| This file contains the i386ex console I/O package. It is just a termios +| wrapper. ++--------------------------------------------------------------------------+ +| (C) Copyright 1997 - +| - NavIST Group - Real-Time Distributed Systems and Industrial Automation +| +| http://pandora.ist.utl.pt +| +| Instituto Superior Tecnico * Lisboa * PORTUGAL ++--------------------------------------------------------------------------+ +| Disclaimer: +| +| This file is provided "AS IS" without warranty of any kind, either +| expressed or implied. ++--------------------------------------------------------------------------+ +| This code is based on: +| console.c,v 1.4 1995/12/19 20:07:23 joel Exp - go32 BSP +| console.c,v 1.15 pc386 BSP +| With the following copyright notice: +| ************************************************************************** +| * 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 found in the file LICENSE in this distribution or at +| * http://www.OARcorp.com/rtems/license.html. +| ************************************************************************** +| +| $Id$ ++--------------------------------------------------------------------------*/ + +#include <stdio.h> +#include <stdlib.h> +#include <assert.h> -#define F386_INIT +/* workaround for gcc development tools */ +#undef __assert +void __assert (const char *file, int line, const char *msg); #include <bsp.h> +#include <irq.h> #include <rtems/libio.h> -#include <bspIo.h> -#include <stdlib.h> +#include <termios.h> +#include <uart.h> +#include <libcpu/cpuModel.h> -#include "../start/80386ex.h" - -/* console_cleanup - * - * This routine is called at exit to clean up the console hardware. - * - * Input parameters: NONE - * - * Output parameters: NONE - * - * Return values: +/* + * Possible value for console input/output : + * BSP_UART_COM1 + * BSP_UART_COM2 + * BSP_CONSOLE_PORT_CONSOLE is not valid in this BSP. + * All references to either keyboard or video handling have been removed. */ -void console_cleanup( void ) -{ - register rtems_unsigned8 ignored; +int BSPConsolePort = BSP_UART_COM2; +int BSPBaseBaud = 781250; +int BSP_poll_read(int); + +extern BSP_polling_getchar_function_type BSP_poll_char; -/* clear the read buffer */ +static int conSetAttr(int minor, const struct termios *); +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 *); + +/* + * Change references to com2 if required. + */ - inport_byte( RBR0, ignored ); +static rtems_irq_connect_data console_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; } -/* console_initialize - * - * This routine initializes the console IO driver. - * - * Input parameters: NONE - * - * Output parameters: NONE - * - * Return values: - */ +static int +isr_is_on(const rtems_irq_connect_data *irq) +{ + return BSP_irq_enabled_at_i8259s(irq->name); +} -rtems_device_driver console_initialize( - rtems_device_major_number major, - rtems_device_minor_number minor, - void *arg -) +void console_reserve_resources(rtems_configuration_table *conf) { - rtems_status_code status; + rtems_termios_reserve_resources(conf, 1); + return; +} +void __assert (const char *file, int line, const char *msg) +{ + static char exit_msg[] = "EXECUTIVE SHUTDOWN! Any key to reboot..."; + unsigned char ch; + /* - * flush the console now and at exit. Just in case. + * Note we cannot call exit or printf from here, + * assert can fail inside ISR too */ - console_cleanup(); + /* + * Close console + */ + __rtems_close(2); + __rtems_close(1); + __rtems_close(0); + + printk("\nassert failed: %s: ", file); + printk("%d: ", line); + printk("%s\n\n", msg); + printk(exit_msg); + ch = BSP_poll_char(); + printk("\nShould jump to reset now!\n"); +} - status = rtems_io_register_name( - "/dev/console", - major, - (rtems_device_minor_number) 0 - ); - - if (status != RTEMS_SUCCESSFUL) + +/*-------------------------------------------------------------------------+ +| Console device driver INITIALIZE entry point. ++--------------------------------------------------------------------------+ +| Initilizes the I/O console (keyboard + VGA display) driver. ++--------------------------------------------------------------------------*/ +rtems_device_driver +console_initialize(rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg) +{ + rtems_status_code status; + + /* + * Set up TERMIOS + */ + rtems_termios_initialize (); + + /* + * Do device-specific initialization + */ + + /* 9600-8-N-1, no hardware flow control */ + BSP_uart_init(BSPConsolePort, 9600, 0); + + + /* Set interrupt handler */ + if(BSPConsolePort == BSP_UART_COM1) + { + console_isr_data.name = BSP_UART_COM1_IRQ; + console_isr_data.hdl = BSP_uart_termios_isr_com1; + + } + else + { + assert(BSPConsolePort == BSP_UART_COM2); + console_isr_data.name = BSP_UART_COM2_IRQ; + console_isr_data.hdl = BSP_uart_termios_isr_com2; + } + + status = BSP_install_rtems_irq_handler(&console_isr_data); + + if (!status){ + printk("Error installing serial console interrupt handler!\n"); rtems_fatal_error_occurred(status); - - atexit( console_cleanup ); + } + /* + * Register the device + */ + status = rtems_io_register_name ("/dev/console", major, 0); + if (status != RTEMS_SUCCESSFUL) + { + printk("Error registering console device!\n"); + rtems_fatal_error_occurred (status); + } + + if(BSPConsolePort == BSP_UART_COM1) + { + printk("Initialized console on port COM1 9600-8-N-1\n\n"); + } + else + { + printk("Initialized console on port COM2 9600-8-N-1\n\n"); + } return RTEMS_SUCCESSFUL; -} +} /* console_initialize */ -/* is_character_ready - * - * This routine returns TRUE if a character is available. - * - * Input parameters: NONE - * - * Output parameters: NONE - * - * Return values: - */ +static int console_open_count = 0; -rtems_boolean is_character_ready( - char *ch -) +static int console_last_close(int major, int minor, void *arg) { - register rtems_unsigned8 status; + BSP_remove_rtems_irq_handler (&console_isr_data); - inport_byte( LSR1, status ); - - if ( Is_rx_ready( status ) ) { - inport_byte( RBR1, status ); - *ch = status; - return TRUE; - } - return FALSE; + return 0; } -/* - * Wait for an input. May be used before intr are ON. - */ -char BSP_wait_polled_input( void ) +/*-------------------------------------------------------------------------+ +| Console device driver OPEN entry point ++--------------------------------------------------------------------------*/ +rtems_device_driver +console_open(rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg) { - char c; - while (!is_character_ready(&c)) - continue; - - return c; -} - -/* inbyte - * - * This routine reads a character from the UART. - * - * Input parameters: NONE - * - * Output parameters: NONE - * - * Return values: - * character read from UART - */ + rtems_status_code status; + static rtems_termios_callbacks cb = + { + NULL, /* firstOpen */ + console_last_close, /* lastClose */ + NULL, /* poll read */ + BSP_uart_termios_write_com2, /* write */ + conSetAttr, /* setAttributes */ + NULL, /* stopRemoteTx */ + NULL, /* startRemoteTx */ + 1 /* outputUsesInterrupts */ + }; + + if(BSPConsolePort == BSP_UART_COM2) + { + cb.write = BSP_uart_termios_write_com2; + } -char inbyte( void ) -{ - register rtems_unsigned8 status; - char ch; + status = rtems_termios_open (major, minor, arg, &cb); - do { - inport_byte( LSR1, status ); - } while ( !( status & 0x01 ));/* s/b while ( !( Is_rx_ready( status ) ) ); */ + if(status != RTEMS_SUCCESSFUL) + { + printk("Error openning console device\n"); + return status; + } - inport_byte( RBR1, ch ); + /* + * Pass data area info down to driver + */ + BSP_uart_termios_set(BSPConsolePort, + ((rtems_libio_open_close_args_t *)arg)->iop->data1); + + /* Enable interrupts on channel */ + BSP_uart_intr_ctrl(BSPConsolePort, BSP_UART_INTR_CTRL_TERMIOS); - return ch; + return RTEMS_SUCCESSFUL; } -/* outbyte - * - * This routine transmits a character out the port. It supports - * XON/XOFF flow control. - * - * Input parameters: - * ch - character to be transmitted - * - * Output parameters: NONE - */ - -void outbyte( - char ch -) +/*-------------------------------------------------------------------------+ +| Console device driver CLOSE entry point ++--------------------------------------------------------------------------*/ +rtems_device_driver +console_close(rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg) { - rtems_unsigned8 status; - do { - inport_byte( LSR1, status ); - } while ( ! ( 0x40 & status ) ); /* ( Is_tx_ready( status ) ) );*/ - -/* - * GDB will NOT use XON/XOFF protocol - */ - - -#ifdef USE_XON + return (rtems_termios_close (arg)); - while ( is_character_ready( &status ) == TRUE ) { - if ( status == XOFF ) - do { - while ( is_character_ready( &status ) == FALSE ) ; - } while ( status != XON ); - } +} /* console_close */ -#endif + +/*-------------------------------------------------------------------------+ +| Console device driver READ entry point. ++--------------------------------------------------------------------------+ +| Read characters from the I/O console. We only have stdin. ++--------------------------------------------------------------------------*/ +rtems_device_driver +console_read(rtems_device_major_number major, + rtems_device_minor_number minor, + void *arg) +{ + rtems_status_code sc; + printf("read the console\n"); - outport_byte( TBR1, ch ); + sc = rtems_termios_read (arg); -} + if ( sc != RTEMS_SUCCESSFUL ) + printf("console_read: fails %s\n",rtems_status_text(sc)); -/* - * Open entry point - */ + return sc; + +} /* console_read */ -rtems_device_driver console_open( - rtems_device_major_number major, - rtems_device_minor_number minor, - void * arg -) + +/*-------------------------------------------------------------------------+ +| Console device driver WRITE entry point. ++--------------------------------------------------------------------------+ +| Write characters to the I/O console. Stderr and stdout are the same. ++--------------------------------------------------------------------------*/ +rtems_device_driver +console_write(rtems_device_major_number major, + rtems_device_minor_number minor, + void * arg) { - return RTEMS_SUCCESSFUL; -} + return rtems_termios_write (arg); -/* - * Close entry point - */ - -rtems_device_driver console_close( - rtems_device_major_number major, - rtems_device_minor_number minor, - void * arg -) -{ - return RTEMS_SUCCESSFUL; -} +} /* console_write */ + + /* - * read bytes from the serial port. We only have stdin. + * Handle ioctl request. */ - -rtems_device_driver console_read( - rtems_device_major_number major, - rtems_device_minor_number minor, - void * arg +rtems_device_driver +console_control(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'; - break; - } - } - - rw_args->bytes_moved = count; - return (count >= 0) ? RTEMS_SUCCESSFUL : RTEMS_UNSATISFIED; +{ + return rtems_termios_ioctl (arg); } -/* - * 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 -) +static int +conSetAttr(int minor, const struct termios *t) { - 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'); + 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; } - outbyte( buffer[ count ] ); - } - - rw_args->bytes_moved = maximum; + + BSP_uart_set_baud(BSPConsolePort, baud); + return 0; } - + /* - * IO Control entry point + * BSP initialization */ - -rtems_device_driver console_control( - rtems_device_major_number major, - rtems_device_minor_number minor, - void * arg -) -{ - return RTEMS_SUCCESSFUL; -} -BSP_output_char_function_type BSP_output_char = outbyte; -BSP_polling_getchar_function_type BSP_poll_char = BSP_wait_polled_input; +BSP_output_char_function_type BSP_output_char = + (BSP_output_char_function_type) BSP_output_char_via_serial; + +BSP_polling_getchar_function_type BSP_poll_char = + (BSP_polling_getchar_function_type) BSP_poll_char_via_serial; +int BSP_poll_read(int ttyMinor){ + + return BSP_poll_char_via_serial(); +} diff --git a/c/src/lib/libbsp/i386/i386ex/start/Makefile.in b/c/src/lib/libbsp/i386/i386ex/start/Makefile.in index 985de4574c..aff674dbba 100644 --- a/c/src/lib/libbsp/i386/i386ex/start/Makefile.in +++ b/c/src/lib/libbsp/i386/i386ex/start/Makefile.in @@ -36,6 +36,7 @@ include $(RTEMS_ROOT)/make/leaf.cfg ifeq ($(RTEMS_GAS_CODE16),yes) DEFINES += -DNEXT_GAS endif + CPPFLAGS += CFLAGS += diff --git a/c/src/lib/libbsp/i386/i386ex/startup/Makefile.in b/c/src/lib/libbsp/i386/i386ex/startup/Makefile.in index 81809a2405..c12bd4662f 100644 --- a/c/src/lib/libbsp/i386/i386ex/startup/Makefile.in +++ b/c/src/lib/libbsp/i386/i386ex/startup/Makefile.in @@ -4,17 +4,15 @@ @SET_MAKE@ srcdir = @srcdir@ -VPATH = @srcdir@:@srcdir@/../../../shared +VPATH = @srcdir@:@srcdir@/../../../shared:@srcdir@/../../shared/comm:@srcdir@/../../shared/irq:@srcdir@/../../shared/io RTEMS_ROOT = @top_srcdir@ PROJECT_ROOT = @PROJECT_ROOT@ PGM=${ARCH}/startup.rel -IMPORT_SRC=$(srcdir)/../../shared/irq/irq.c \ - $(srcdir)/../../shared/irq/irq_init.c $(srcdir)/../../shared/irq/irq_asm.s - # C source names, if any, go here -- minus the .c -C_PIECES=bspclean bsplibc bsppost bspstart main sbrk irq irq_init +C_PIECES=bspclean bsplibc bsppost bspstart main sbrk irq irq_init i386-stub-glue uart i386-stub + C_FILES=$(C_PIECES:%=%.c) C_O_FILES=$(C_PIECES:%=${ARCH}/%.o) @@ -37,7 +35,8 @@ include $(RTEMS_ROOT)/make/leaf.cfg # #DEFINES += -DPRINTON -DEFINES += -I$(srcdir) + +DEFINES += -I$(srcdir) -DBSP_IS_I386EX=1 CPPFLAGS += CFLAGS += -g @@ -56,7 +55,9 @@ CLEAN_ADDITIONS += CLOBBER_ADDITIONS += preinstall: - ${CP} ${IMPORT_SRC} . + $(INSTALL) ${IMPORT_SRC} . + +# ${CP} ${IMPORT_SRC} . ${PGM}: ${SRCS} ${OBJS} $(make-rel) diff --git a/c/src/lib/libbsp/i386/i386ex/timer/timer.c b/c/src/lib/libbsp/i386/i386ex/timer/timer.c index 954bd7f6dd..208c5442a1 100644 --- a/c/src/lib/libbsp/i386/i386ex/timer/timer.c +++ b/c/src/lib/libbsp/i386/i386ex/timer/timer.c @@ -55,7 +55,7 @@ void TimerOn(const rtems_raw_irq_connect_data* used) /* * enable interrrupt at i8259 level */ - pc386_irq_enable_at_i8259s(used->idtIndex - PC386_IRQ_VECTOR_BASE); + BSP_irq_enable_at_i8259s(used->idtIndex - BSP_IRQ_VECTOR_BASE); } void TimerOff(const rtems_raw_irq_connect_data* used) @@ -63,12 +63,12 @@ void TimerOff(const rtems_raw_irq_connect_data* used) /* * disable interrrupt at i8259 level */ - pc386_irq_disable_at_i8259s(used->idtIndex - PC386_IRQ_VECTOR_BASE); + BSP_irq_disable_at_i8259s(used->idtIndex - BSP_IRQ_VECTOR_BASE); /* reset timer mode to standard (DOS) value */ } static rtems_raw_irq_connect_data timer_raw_irq_data = { - PC_386_RT_TIMER3 + PC386_IRQ_VECTOR_BASE, + BSP_RT_TIMER3 + BSP_IRQ_VECTOR_BASE, timerisr, TimerOn, TimerOff, diff --git a/c/src/lib/libbsp/i386/pc386/Makefile.in b/c/src/lib/libbsp/i386/pc386/Makefile.in index 4862454e13..68582b5145 100644 --- a/c/src/lib/libbsp/i386/pc386/Makefile.in +++ b/c/src/lib/libbsp/i386/pc386/Makefile.in @@ -17,5 +17,5 @@ NETWORK = $(NETWORK_$(HAS_NETWORKING)_V) # wrapup is the one that actually builds and installs the library # from the individual .rel files built in other directories -SUB_DIRS=include tools start startup clock console timer pc386dev $(NETWORK) \ +SUB_DIRS=include tools start startup clock console timer $(NETWORK) \ wrapup diff --git a/c/src/lib/libbsp/i386/pc386/clock/ckinit.c b/c/src/lib/libbsp/i386/pc386/clock/ckinit.c index f3687d1e66..ee252a1e44 100644 --- a/c/src/lib/libbsp/i386/pc386/clock/ckinit.c +++ b/c/src/lib/libbsp/i386/pc386/clock/ckinit.c @@ -176,7 +176,7 @@ int clockIsOn(const rtems_irq_connect_data* unused) return ((i8259s_cache & 0x1) == 0); } -static rtems_irq_connect_data clockIrqData = {PC_386_PERIODIC_TIMER, +static rtems_irq_connect_data clockIrqData = {BSP_PERIODIC_TIMER, clockIsr, clockOn, clockOff, @@ -195,7 +195,7 @@ Clock_initialize(rtems_device_major_number major, void *pargp) { - if (!pc386_install_rtems_irq_handler (&clockIrqData)) { + if (!BSP_install_rtems_irq_handler (&clockIrqData)) { printk("Unable to initialize system clock\n"); rtems_fatal_error_occurred(1); } @@ -229,7 +229,7 @@ Clock_control(rtems_device_major_number major, clockIsr(); else if (args->command == rtems_build_name('N', 'E', 'W', ' ')) { - if (!pc386_install_rtems_irq_handler (&clockIrqData)) { + if (!BSP_install_rtems_irq_handler (&clockIrqData)) { printk("Error installing clock interrupt handler!\n"); rtems_fatal_error_occurred(1); } @@ -241,7 +241,7 @@ Clock_control(rtems_device_major_number major, void Clock_exit() { - pc386_remove_rtems_irq_handler (&clockIrqData); + BSP_remove_rtems_irq_handler (&clockIrqData); } /*-------------------------------------------------------------------------+ diff --git a/c/src/lib/libbsp/i386/pc386/console/console.c b/c/src/lib/libbsp/i386/pc386/console/console.c index 23268bdd06..7a07a6ca3f 100644 --- a/c/src/lib/libbsp/i386/pc386/console/console.c +++ b/c/src/lib/libbsp/i386/pc386/console/console.c @@ -34,29 +34,34 @@ #include <stdio.h> #include <stdlib.h> #include <assert.h> +#undef __assert +void __assert (const char *file, int line, const char *msg); #include <bsp.h> #include <irq.h> #include <rtems/libio.h> #include <termios.h> -#include <pc386uart.h> +#include <uart.h> #include <libcpu/cpuModel.h> /* * Possible value for console input/output : - * PC386_CONSOLE_PORT_CONSOLE - * PC386_UART_COM1 - * PC386_UART_COM2 + * BSP_CONSOLE_PORT_CONSOLE + * BSP_UART_COM1 + * BSP_UART_COM2 */ /* * Possible value for console input/output : - * PC386_CONSOLE_PORT_CONSOLE - * PC386_UART_COM1 - * PC386_UART_COM2 + * BSP_CONSOLE_PORT_CONSOLE + * BSP_UART_COM1 + * BSP_UART_COM2 */ -int PC386ConsolePort = PC386_CONSOLE_PORT_CONSOLE; +int BSPConsolePort = BSP_CONSOLE_PORT_CONSOLE; + +/* int BSPConsolePort = BSP_UART_COM2; */ +int BSPBaseBaud = 115200; extern BSP_polling_getchar_function_type BSP_poll_char; @@ -66,6 +71,7 @@ extern BSP_polling_getchar_function_type BSP_poll_char; extern void _IBMPC_keyboard_isr(void); extern rtems_boolean _IBMPC_scankey(char *); /* defined in 'inch.c' */ extern char BSP_wait_polled_input(void); +extern void _IBMPC_initVideo(void); static int conSetAttr(int minor, const struct termios *); static void isr_on(const rtems_irq_connect_data *); @@ -73,7 +79,7 @@ static void isr_off(const rtems_irq_connect_data *); static int isr_is_on(const rtems_irq_connect_data *); -static rtems_irq_connect_data console_isr_data = {PC_386_KEYBOARD, +static rtems_irq_connect_data console_isr_data = {BSP_KEYBOARD, _IBMPC_keyboard_isr, isr_on, isr_off, @@ -94,28 +100,30 @@ isr_off(const rtems_irq_connect_data *unused) static int isr_is_on(const rtems_irq_connect_data *irq) { - return pc386_irq_enabled_at_i8259s(irq->name); + return BSP_irq_enabled_at_i8259s(irq->name); } void console_reserve_resources(rtems_configuration_table *conf) { - if(PC386ConsolePort != PC386_CONSOLE_PORT_CONSOLE) + if(BSPConsolePort != BSP_CONSOLE_PORT_CONSOLE) { rtems_termios_reserve_resources(conf, 1); } + return; } -void __assert(const char *file, int line, const char *msg) +void __assert (const char *file, int line, const char *msg) { - static char exit_msg[] = "EXECUTIVE SHUTDOWN! Any key to reboot..."; + static char exit_msg[] = "EXECUTIVE SHUTDOWN! Any key to reboot..."; unsigned char ch; - + /* * Note we cannot call exit or printf from here, * assert can fail inside ISR too */ - /* + + /* * Close console */ __rtems_close(2); @@ -129,6 +137,7 @@ void __assert(const char *file, int line, const char *msg) ch = BSP_poll_char(); printk("\n\n"); rtemsReboot(); + } @@ -149,11 +158,11 @@ console_initialize(rtems_device_major_number major, * to be reinitialized. */ - if(PC386ConsolePort == PC386_CONSOLE_PORT_CONSOLE) - { + if(BSPConsolePort == BSP_CONSOLE_PORT_CONSOLE) + { /* Install keyboard interrupt handler */ - status = pc386_install_rtems_irq_handler(&console_isr_data); + status = BSP_install_rtems_irq_handler(&console_isr_data); if (!status) { @@ -181,24 +190,24 @@ console_initialize(rtems_device_major_number major, */ /* 9600-8-N-1 */ - PC386_uart_init(PC386ConsolePort, 9600, 0); + BSP_uart_init(BSPConsolePort, 9600, 0); /* Set interrupt handler */ - if(PC386ConsolePort == PC386_UART_COM1) + if(BSPConsolePort == BSP_UART_COM1) { - console_isr_data.name = PC386_UART_COM1_IRQ; - console_isr_data.hdl = PC386_uart_termios_isr_com1; + console_isr_data.name = BSP_UART_COM1_IRQ; + console_isr_data.hdl = BSP_uart_termios_isr_com1; } else { - assert(PC386ConsolePort == PC386_UART_COM2); - console_isr_data.name = PC386_UART_COM2_IRQ; - console_isr_data.hdl = PC386_uart_termios_isr_com2; + assert(BSPConsolePort == BSP_UART_COM2); + console_isr_data.name = BSP_UART_COM2_IRQ; + console_isr_data.hdl = BSP_uart_termios_isr_com2; } - status = pc386_install_rtems_irq_handler(&console_isr_data); + status = BSP_install_rtems_irq_handler(&console_isr_data); if (!status){ printk("Error installing serial console interrupt handler!\n"); @@ -214,7 +223,7 @@ console_initialize(rtems_device_major_number major, rtems_fatal_error_occurred (status); } - if(PC386ConsolePort == PC386_UART_COM1) + if(BSPConsolePort == BSP_UART_COM1) { printk("Initialized console on port COM1 9600-8-N-1\n\n"); } @@ -229,7 +238,7 @@ console_initialize(rtems_device_major_number major, * using the video console for output while printf use serial line. * This may be convenient to debug the serial line driver itself... */ - printk("Warning : This will be the last message displayed on console\n"); + /* printk("Warning : This will be the last message displayed on console\n");*/ BSP_output_char = (BSP_output_char_function_type) BSP_output_char_via_serial; BSP_poll_char = (BSP_polling_getchar_function_type) BSP_poll_char_via_serial; #endif @@ -242,7 +251,7 @@ static int console_open_count = 0; static int console_last_close(int major, int minor, void *arg) { - pc386_remove_rtems_irq_handler (&console_isr_data); + BSP_remove_rtems_irq_handler (&console_isr_data); return 0; } @@ -261,22 +270,22 @@ console_open(rtems_device_major_number major, NULL, /* firstOpen */ console_last_close, /* lastClose */ NULL, /* pollRead */ - PC386_uart_termios_write_com1, /* write */ + BSP_uart_termios_write_com1, /* write */ conSetAttr, /* setAttributes */ NULL, /* stopRemoteTx */ NULL, /* startRemoteTx */ 1 /* outputUsesInterrupts */ }; - if(PC386ConsolePort == PC386_CONSOLE_PORT_CONSOLE) + if(BSPConsolePort == BSP_CONSOLE_PORT_CONSOLE) { ++console_open_count; return RTEMS_SUCCESSFUL; } - if(PC386ConsolePort == PC386_UART_COM2) + if(BSPConsolePort == BSP_UART_COM2) { - cb.write = PC386_uart_termios_write_com2; + cb.write = BSP_uart_termios_write_com2; } status = rtems_termios_open (major, minor, arg, &cb); @@ -290,11 +299,11 @@ console_open(rtems_device_major_number major, /* * Pass data area info down to driver */ - PC386_uart_termios_set(PC386ConsolePort, + BSP_uart_termios_set(BSPConsolePort, ((rtems_libio_open_close_args_t *)arg)->iop->data1); /* Enable interrupts on channel */ - PC386_uart_intr_ctrl(PC386ConsolePort, PC386_UART_INTR_CTRL_TERMIOS); + BSP_uart_intr_ctrl(BSPConsolePort, BSP_UART_INTR_CTRL_TERMIOS); return RTEMS_SUCCESSFUL; } @@ -309,7 +318,7 @@ console_close(rtems_device_major_number major, { rtems_device_driver res = RTEMS_SUCCESSFUL; - if(PC386ConsolePort != PC386_CONSOLE_PORT_CONSOLE) + if(BSPConsolePort != BSP_CONSOLE_PORT_CONSOLE) { res = rtems_termios_close (arg); } @@ -337,7 +346,7 @@ console_read(rtems_device_major_number major, char *buffer = rw_args->buffer; int count, maximum = rw_args->count; - if(PC386ConsolePort != PC386_CONSOLE_PORT_CONSOLE) + if(BSPConsolePort != BSP_CONSOLE_PORT_CONSOLE) { return rtems_termios_read (arg); } @@ -382,7 +391,7 @@ console_write(rtems_device_major_number major, char *buffer = rw_args->buffer; int count, maximum = rw_args->count; - if(PC386ConsolePort != PC386_CONSOLE_PORT_CONSOLE) + if(BSPConsolePort != BSP_CONSOLE_PORT_CONSOLE) { return rtems_termios_write (arg); } @@ -409,7 +418,7 @@ console_control(rtems_device_major_number major, void * arg ) { - if(PC386ConsolePort != PC386_CONSOLE_PORT_CONSOLE) + if(BSPConsolePort != BSP_CONSOLE_PORT_CONSOLE) { return rtems_termios_ioctl (arg); } @@ -481,7 +490,7 @@ conSetAttr(int minor, const struct termios *t) return 0; } - PC386_uart_set_baud(PC386ConsolePort, baud); + BSP_uart_set_baud(BSPConsolePort, baud); return 0; } diff --git a/c/src/lib/libbsp/i386/pc386/include/bsp.h b/c/src/lib/libbsp/i386/pc386/include/bsp.h index 002bf3b587..f18bdb375d 100644 --- a/c/src/lib/libbsp/i386/pc386/include/bsp.h +++ b/c/src/lib/libbsp/i386/pc386/include/bsp.h @@ -160,10 +160,10 @@ void printk(char *fmt, ...); /* from 'printk.c' */ void rtemsReboot(void); /* from 'exit.c' */ -/* Definitions for PC386ConsolePort */ -#define PC386_CONSOLE_PORT_CONSOLE (-1) -#define PC386_CONSOLE_PORT_COM1 (PC386_UART_COM1) -#define PC386_CONSOLE_PORT_COM2 (PC386_UART_COM2) +/* Definitions for BSPConsolePort */ +#define BSP_CONSOLE_PORT_CONSOLE (-1) +#define BSP_CONSOLE_PORT_COM1 (BSP_UART_COM1) +#define BSP_CONSOLE_PORT_COM2 (BSP_UART_COM2) /* GDB stub stuff */ void i386_stub_glue_init(int uart); diff --git a/c/src/lib/libbsp/i386/pc386/start/Makefile.in b/c/src/lib/libbsp/i386/pc386/start/Makefile.in index e085f50e5b..08007d952d 100644 --- a/c/src/lib/libbsp/i386/pc386/start/Makefile.in +++ b/c/src/lib/libbsp/i386/pc386/start/Makefile.in @@ -33,9 +33,9 @@ include $(RTEMS_ROOT)/make/leaf.cfg # (OPTIONAL) Add local stuff here using += # -ifeq ($(RTEMS_GAS_CODE16),yes) +#ifeq ($(RTEMS_GAS_CODE16),yes) DEFINES += -DNEXT_GAS -endif +#endif CPPFLAGS += CFLAGS += diff --git a/c/src/lib/libbsp/i386/pc386/start/start16.s b/c/src/lib/libbsp/i386/pc386/start/start16.s index d09430e0af..4b12408cd6 100644 --- a/c/src/lib/libbsp/i386/pc386/start/start16.s +++ b/c/src/lib/libbsp/i386/pc386/start/start16.s @@ -33,7 +33,7 @@ .set HDROFF, 0x24 # offset into bin2boot header of start32 addr .set STACKOFF, 0x200-0x10 # offset to load into %esp, from start of image -/* #define NEW_GAS*/ + /* #define NEW_GAS */ /*----------------------------------------------------------------------------+ | CODE section +----------------------------------------------------------------------------*/ diff --git a/c/src/lib/libbsp/i386/pc386/startup/Makefile.in b/c/src/lib/libbsp/i386/pc386/startup/Makefile.in index b59323c6ff..c0da505e2d 100644 --- a/c/src/lib/libbsp/i386/pc386/startup/Makefile.in +++ b/c/src/lib/libbsp/i386/pc386/startup/Makefile.in @@ -4,14 +4,14 @@ @SET_MAKE@ srcdir = @srcdir@ -VPATH = @srcdir@:@srcdir@/../../../shared:@srcdir@/../../shared/irq +VPATH = @srcdir@:@srcdir@/../../../shared:@srcdir@/../../shared/irq:@srcdir@/../../shared/comm:@srcdir@/../../shared/pci RTEMS_ROOT = @top_srcdir@ PROJECT_ROOT = @PROJECT_ROOT@ PGM=${ARCH}/startup.rel # C source names, if any, go here -- minus the .c -C_PIECES=bsplibc bsppost bspstart exit irq irq_init main sbrk +C_PIECES=bsplibc bsppost bspstart exit irq irq_init main sbrk i386-stub i386-stub-glue uart pcibios C_FILES=$(C_PIECES:%=%.c) C_O_FILES=$(C_PIECES:%=${ARCH}/%.o) diff --git a/c/src/lib/libbsp/i386/pc386/startup/bspstart.c b/c/src/lib/libbsp/i386/pc386/startup/bspstart.c index 5800cfad6e..a14ff0521f 100644 --- a/c/src/lib/libbsp/i386/pc386/startup/bspstart.c +++ b/c/src/lib/libbsp/i386/pc386/startup/bspstart.c @@ -146,6 +146,7 @@ void bsp_start( void ) /* * Initialize printk channel */ + _IBMPC_initVideo(); rtemsFreeMemStart = (rtems_unsigned32)&_end + _stack_size; diff --git a/c/src/lib/libbsp/i386/pc386/startup/exit.c b/c/src/lib/libbsp/i386/pc386/startup/exit.c index a9f11b9be4..c37888f003 100644 --- a/c/src/lib/libbsp/i386/pc386/startup/exit.c +++ b/c/src/lib/libbsp/i386/pc386/startup/exit.c @@ -35,7 +35,7 @@ #include <stdio.h> #include <bsp.h> #include <rtems/libio.h> -#include <pc386uart.h> +#include <uart.h> void bsp_cleanup(void) { diff --git a/c/src/lib/libbsp/i386/pc386/startup/linkcmds b/c/src/lib/libbsp/i386/pc386/startup/linkcmds index 5dd7a675a3..f66952b04c 100644 --- a/c/src/lib/libbsp/i386/pc386/startup/linkcmds +++ b/c/src/lib/libbsp/i386/pc386/startup/linkcmds @@ -62,7 +62,6 @@ SECTIONS _rodata_start = . ; *(.rodata) - *(.gnu.linkonce.r*) _erodata = ALIGN( 0x10 ) ; _etext = ALIGN( 0x10 ) ; diff --git a/c/src/lib/libbsp/i386/pc386/timer/timer.c b/c/src/lib/libbsp/i386/pc386/timer/timer.c index 47e4894e00..4c83b309dd 100644 --- a/c/src/lib/libbsp/i386/pc386/timer/timer.c +++ b/c/src/lib/libbsp/i386/pc386/timer/timer.c @@ -167,7 +167,7 @@ timerOff(const rtems_raw_irq_connect_data* used) /* * disable interrrupt at i8259 level */ - pc386_irq_disable_at_i8259s(used->idtIndex - PC386_IRQ_VECTOR_BASE); + BSP_irq_disable_at_i8259s(used->idtIndex - BSP_IRQ_VECTOR_BASE); /* reset timer mode to standard (DOS) value */ outport_byte(TIMER_MODE, TIMER_SEL0|TIMER_16BIT|TIMER_RATEGEN); outport_byte(TIMER_CNTR0, 0); @@ -185,16 +185,16 @@ timerOn(const rtems_raw_irq_connect_data* used) /* * enable interrrupt at i8259 level */ - pc386_irq_enable_at_i8259s(used->idtIndex - PC386_IRQ_VECTOR_BASE); + BSP_irq_enable_at_i8259s(used->idtIndex - BSP_IRQ_VECTOR_BASE); } static int timerIsOn(const rtems_raw_irq_connect_data *used) { - return pc386_irq_enabled_at_i8259s(used->idtIndex - PC386_IRQ_VECTOR_BASE);} + return BSP_irq_enabled_at_i8259s(used->idtIndex - BSP_IRQ_VECTOR_BASE);} static rtems_raw_irq_connect_data timer_raw_irq_data = { - PC_386_PERIODIC_TIMER + PC386_IRQ_VECTOR_BASE, + BSP_PERIODIC_TIMER + BSP_IRQ_VECTOR_BASE, timerisr, timerOn, timerOff, diff --git a/c/src/lib/libbsp/i386/pc386/wrapup/Makefile.in b/c/src/lib/libbsp/i386/pc386/wrapup/Makefile.in index 70515fdb8e..86462939cf 100644 --- a/c/src/lib/libbsp/i386/pc386/wrapup/Makefile.in +++ b/c/src/lib/libbsp/i386/pc386/wrapup/Makefile.in @@ -12,7 +12,7 @@ PROJECT_ROOT = @PROJECT_ROOT@ NETWORK_yes_V = network NETWORK = $(NETWORK_$(HAS_NETWORKING)_V) -BSP_PIECES=startup clock console timer pc386dev $(NETWORK) +BSP_PIECES=startup clock console timer $(NETWORK) GENERIC_PIECES= # bummer; have to use $foreach since % pattern subst rules only replace 1x diff --git a/c/src/lib/libbsp/i386/shared/Makefile.in b/c/src/lib/libbsp/i386/shared/Makefile.in index 6fc07991ea..cee2697aae 100644 --- a/c/src/lib/libbsp/i386/shared/Makefile.in +++ b/c/src/lib/libbsp/i386/shared/Makefile.in @@ -12,5 +12,5 @@ include $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg include $(RTEMS_ROOT)/make/directory.cfg # Descend into the $(RTEMS_BSP_FAMILY) directory -SUB_DIRS=irq io +SUB_DIRS=irq io comm pci diff --git a/c/src/lib/libbsp/i386/shared/comm/GDB.HOWTO b/c/src/lib/libbsp/i386/shared/comm/GDB.HOWTO new file mode 100644 index 0000000000..0fdfad02ea --- /dev/null +++ b/c/src/lib/libbsp/i386/shared/comm/GDB.HOWTO @@ -0,0 +1,177 @@ +1. Add GDB initilization to your target's code: + +a) include file: + +#include <uart.h> + +b) declare this variable: + +extern int BSPConsolePort; + +c) To start-up GDB, run this: + + /* Init GDB glue */ + + if(BSPConsolePort != BSP_UART_COM2) + { + /* + * If com2 is not used as console use it for + * debugging + */ + i386_stub_glue_init(BSP_UART_COM2); + } + else + { + /* Otherwise use com1 */ + i386_stub_glue_init(BSP_UART_COM1); + } + + /* Init GDB stub itself */ + set_debug_traps(); + + /* + * Init GDB break in capability, + * has to be called after + * set_debug_traps + */ + i386_stub_glue_init_breakin(); + + /* Put breakpoint in */ + breakpoint(); + +d) This is all you need to do for the target. + +2. Edit cmds: specify path to current directory and device used for debugging + example of cmds is attached below. Make sure your paths are correct. +3. type 'make' +4. Boot o-pc386/<test>.exe on target computer, where <test> has the code from step 1. ( I modified and recompiled base_sp as the <test> ) +5. run 'i396-rtems-gdb --nx --command=./cmds o-pc386/<test>.coff + +=========================== example cmds ============================== +dir /home/cross-19980908/tools/rtems-980923 +dir /home/cross-19980908/tools/rtems-980923/aclocal +dir /home/cross-19980908/tools/rtems-980923/c +dir /home/cross-19980908/tools/rtems-980923/c/build-tools +dir /home/cross-19980908/tools/rtems-980923/c/build-tools/os +dir /home/cross-19980908/tools/rtems-980923/c/build-tools/os/msdos +dir /home/cross-19980908/tools/rtems-980923/c/build-tools/scripts +dir /home/cross-19980908/tools/rtems-980923/c/build-tools/src +dir /home/cross-19980908/tools/rtems-980923/c/src +dir /home/cross-19980908/tools/rtems-980923/c/src/exec +dir /home/cross-19980908/tools/rtems-980923/c/src/exec/posix +dir /home/cross-19980908/tools/rtems-980923/c/src/exec/posix/base +dir /home/cross-19980908/tools/rtems-980923/c/src/exec/posix/headers +dir /home/cross-19980908/tools/rtems-980923/c/src/exec/posix/inline +dir /home/cross-19980908/tools/rtems-980923/c/src/exec/posix/macros +dir /home/cross-19980908/tools/rtems-980923/c/src/exec/posix/optman +dir /home/cross-19980908/tools/rtems-980923/c/src/exec/posix/src +dir /home/cross-19980908/tools/rtems-980923/c/src/exec/posix/sys +dir /home/cross-19980908/tools/rtems-980923/c/src/exec/sapi +dir /home/cross-19980908/tools/rtems-980923/c/src/exec/sapi/headers +dir /home/cross-19980908/tools/rtems-980923/c/src/exec/sapi/src +dir /home/cross-19980908/tools/rtems-980923/c/src/exec/sapi/inline +dir /home/cross-19980908/tools/rtems-980923/c/src/exec/sapi/macros +dir /home/cross-19980908/tools/rtems-980923/c/src/exec/sapi/optman +dir /home/cross-19980908/tools/rtems-980923/c/src/exec/rtems +dir /home/cross-19980908/tools/rtems-980923/c/src/exec/rtems/headers +dir /home/cross-19980908/tools/rtems-980923/c/src/exec/rtems/src +dir /home/cross-19980908/tools/rtems-980923/c/src/exec/rtems/inline +dir /home/cross-19980908/tools/rtems-980923/c/src/exec/rtems/macros +dir /home/cross-19980908/tools/rtems-980923/c/src/exec/rtems/optman +dir /home/cross-19980908/tools/rtems-980923/c/src/exec/score +dir /home/cross-19980908/tools/rtems-980923/c/src/exec/score/cpu +dir /home/cross-19980908/tools/rtems-980923/c/src/exec/score/cpu/a29k +dir /home/cross-19980908/tools/rtems-980923/c/src/exec/score/cpu/hppa1.1 +dir /home/cross-19980908/tools/rtems-980923/c/src/exec/score/cpu/i386 +dir /home/cross-19980908/tools/rtems-980923/c/src/exec/score/cpu/i960 +dir /home/cross-19980908/tools/rtems-980923/c/src/exec/score/cpu/m68k +dir /home/cross-19980908/tools/rtems-980923/c/src/exec/score/cpu/mips64orion +dir /home/cross-19980908/tools/rtems-980923/c/src/exec/score/cpu/no_cpu +dir /home/cross-19980908/tools/rtems-980923/c/src/exec/score/cpu/powerpc +dir /home/cross-19980908/tools/rtems-980923/c/src/exec/score/cpu/sh +dir /home/cross-19980908/tools/rtems-980923/c/src/exec/score/cpu/sparc +dir /home/cross-19980908/tools/rtems-980923/c/src/exec/score/cpu/unix +dir /home/cross-19980908/tools/rtems-980923/c/src/exec/score/headers +dir /home/cross-19980908/tools/rtems-980923/c/src/exec/score/inline +dir /home/cross-19980908/tools/rtems-980923/c/src/exec/score/macros +dir /home/cross-19980908/tools/rtems-980923/c/src/exec/score/src +dir /home/cross-19980908/tools/rtems-980923/c/src/exec/score/tools +dir /home/cross-19980908/tools/rtems-980923/c/src/exec/score/tools/generic +dir /home/cross-19980908/tools/rtems-980923/c/src/exec/score/tools/unix +dir /home/cross-19980908/tools/rtems-980923/c/src/exec/score/tools/hppa1.1 +dir /home/cross-19980908/tools/rtems-980923/c/src/exec/wrapup +dir /home/cross-19980908/tools/rtems-980923/c/src/exec/wrapup/posix +dir /home/cross-19980908/tools/rtems-980923/c/src/exec/wrapup/rtems +dir /home/cross-19980908/tools/rtems-980923/c/src/lib +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/include +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/include/motorola +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/include/rtems++ +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/include/sys +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/include/zilog +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libc +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libbsp +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libbsp/i386 +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libbsp/i386/pc386 +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libbsp/i386/pc386/clock +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libbsp/i386/pc386/console +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libbsp/i386/pc386/include +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libbsp/i386/pc386/start +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libbsp/i386/pc386/startup +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libbsp/i386/pc386/timer +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libbsp/i386/pc386/tools +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libbsp/i386/pc386/wrapup +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libbsp/i386/shared/comm +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libbsp/i386/shared/pci +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libcpu +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libcpu/hppa1.1 +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libcpu/hppa1.1/clock +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libcpu/hppa1.1/include +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libcpu/hppa1.1/milli +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libcpu/hppa1.1/runway +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libcpu/hppa1.1/semaphore +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libcpu/hppa1.1/timer +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libcpu/m68k +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libcpu/m68k/m68040 +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libcpu/m68k/m68040/fpsp +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libcpu/mips64orion +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libcpu/mips64orion/clock +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libcpu/mips64orion/include +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libcpu/mips64orion/timer +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libcpu/powerpc +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libcpu/powerpc/ppc403 +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libcpu/powerpc/ppc403/clock +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libcpu/powerpc/ppc403/console +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libcpu/powerpc/ppc403/include +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libcpu/powerpc/ppc403/timer +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libcpu/powerpc/ppc403/vectors +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libcpu/sh +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libcpu/sh/sh7032 +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libcpu/sh/sh7032/clock +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libcpu/sh/sh7032/null +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libcpu/sh/sh7032/console +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libcpu/sh/sh7032/include +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libcpu/sh/sh7032/timer +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libcpu/sparc +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libcpu/sparc/reg_win +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libnetworking +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libmisc +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libmisc/assoc +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libmisc/cpuuse +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libmisc/error +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libmisc/monitor +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libmisc/rtmonuse +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libmisc/stackchk +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/libmisc/wrapup +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/librtems++ +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/start +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/start/a29k +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/start/i960 +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/start/m68k +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/start/mips64orion +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/start/sh +dir /home/cross-19980908/tools/rtems-980923/c/src/lib/wrapup +dir /home/cross-19980908/tools/rtems-980923/c/src/tests +dir /home/cross-19980908/tools/rtems-980923/c/src/tests/samples +dir /home/cross-19980908/tools/rtems-980923/c/src/tests/samples/base_sp +set remotebaud 38400 +target remote /dev/ttyS1 diff --git a/c/src/lib/libbsp/i386/shared/comm/Makefile.in b/c/src/lib/libbsp/i386/shared/comm/Makefile.in new file mode 100644 index 0000000000..960dd1f2b4 --- /dev/null +++ b/c/src/lib/libbsp/i386/shared/comm/Makefile.in @@ -0,0 +1,33 @@ +# +# $Id$ +# + +@SET_MAKE@ +srcdir = @srcdir@ +VPATH = @srcdir@ +RTEMS_ROOT = @top_srcdir@ +PROJECT_ROOT = @PROJECT_ROOT@ + +H_FILES = $(srcdir)/uart.h + +# +# Equate files are for including from assembly preprocessed by +# gm4 or gasp. No examples are provided except for those for +# other CPUs. The best way to generate them would be to +# provide a program which generates the constants used based +# on the C equivalents. +# + +EQ_FILES = + +SRCS=$(H_FILES) $(EQ_FILES) + +include $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg +include $(RTEMS_ROOT)/make/leaf.cfg + +CLEAN_ADDITIONS += +CLOBBER_ADDITIONS += + +preinstall all: $(SRCS) + $(INSTALL) -m 444 $(SRCS) $(PROJECT_INCLUDE) + diff --git a/c/src/lib/libbsp/i386/shared/comm/i386-stub-glue.c b/c/src/lib/libbsp/i386/shared/comm/i386-stub-glue.c new file mode 100644 index 0000000000..997237c1c2 --- /dev/null +++ b/c/src/lib/libbsp/i386/shared/comm/i386-stub-glue.c @@ -0,0 +1,194 @@ +/* + * This software is Copyright (C) 1998 by T.sqware - all rights limited + * It is provided in to the public domain "as is", can be freely modified + * as far as this copyight notice is kept unchanged, but does not imply + * an endorsement by T.sqware of the product in which it is included. + * + * $Id$ + */ + +#include <rtems/system.h> +#include <rtems/score/cpu.h> +#include <bsp.h> +#include <irq.h> +#include <uart.h> +#include <assert.h> + + +int putDebugChar(int ch); /* write a single character */ +int getDebugChar(void); /* read and return a single char */ + +/* assign an exception handler */ +void exceptionHandler(int, void (*handler)(void)); + + +/* Current uart used by gdb stub */ +static int uart_current = 0; + +/* + * Initialize glue code linking i386-stub with the rest of + * the system + */ +void +i386_stub_glue_init(int uart) +{ + assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2); + + uart_current = uart; + + BSP_uart_init(uart, 38400, 0); +} + +void BSP_uart_on(const rtems_raw_irq_connect_data* used) +{ + BSP_irq_enable_at_i8259s(used->idtIndex - BSP_IRQ_VECTOR_BASE); +} + +void BSP_uart_off(const rtems_raw_irq_connect_data* used) +{ + BSP_irq_disable_at_i8259s(used->idtIndex - BSP_IRQ_VECTOR_BASE); +} + +int BSP_uart_isOn(const rtems_raw_irq_connect_data* used) +{ + return BSP_irq_enabled_at_i8259s(used->idtIndex - BSP_IRQ_VECTOR_BASE); +} + + +/* + * In order to have a possibility to break into + * running program, one has to call this function + */ +void i386_stub_glue_init_breakin(void) +{ + rtems_raw_irq_connect_data uart_raw_irq_data; + + assert(uart_current == BSP_UART_COM1 || uart_current == BSP_UART_COM2); + + if(uart_current == BSP_UART_COM1) + { + uart_raw_irq_data.idtIndex = BSP_UART_COM1_IRQ + BSP_IRQ_VECTOR_BASE; + } + else + { + uart_raw_irq_data.idtIndex = BSP_UART_COM2_IRQ + BSP_IRQ_VECTOR_BASE; + } + + if(!i386_get_current_idt_entry(&uart_raw_irq_data)) + { + printk("cannot get idt entry\n"); + rtems_fatal_error_occurred(1); + } + + if(!i386_delete_idt_entry(&uart_raw_irq_data)) + { + printk("cannot delete idt entry\n"); + rtems_fatal_error_occurred(1); + } + + uart_raw_irq_data.on = BSP_uart_on; + uart_raw_irq_data.off = BSP_uart_off; + uart_raw_irq_data.isOn= BSP_uart_isOn; + + /* Install ISR */ + if(uart_current == BSP_UART_COM1) + { + uart_raw_irq_data.idtIndex = BSP_UART_COM1_IRQ + BSP_IRQ_VECTOR_BASE; + uart_raw_irq_data.hdl = BSP_uart_dbgisr_com1; + } + else + { + uart_raw_irq_data.idtIndex = BSP_UART_COM2_IRQ + BSP_IRQ_VECTOR_BASE; + uart_raw_irq_data.hdl = BSP_uart_dbgisr_com2; + } + + if (!i386_set_idt_entry (&uart_raw_irq_data)) + { + printk("raw exception handler connection failed\n"); + rtems_fatal_error_occurred(1); + } + + /* Enable interrupts */ + BSP_uart_intr_ctrl(uart_current, BSP_UART_INTR_CTRL_GDB); + + return; +} + + +int +putDebugChar(int ch) +{ + assert(uart_current == BSP_UART_COM1 || uart_current == BSP_UART_COM2); + + BSP_uart_polled_write(uart_current, ch); + + return 1; +} + +int getDebugChar(void) +{ + int val; + + assert(uart_current == BSP_UART_COM1 || uart_current == BSP_UART_COM2); + + val = BSP_uart_polled_read(uart_current); + + return val; +} + +static void nop(){} +static int isOn() {return 1;} + +void exceptionHandler(int vector, void (*handler)(void)) +{ + rtems_raw_irq_connect_data excep_raw_irq_data; + + excep_raw_irq_data.idtIndex = vector; + + if(!i386_get_current_idt_entry(&excep_raw_irq_data)) + { + printk("cannot get idt entry\n"); + rtems_fatal_error_occurred(1); + } + + if(!i386_delete_idt_entry(&excep_raw_irq_data)) + { + printk("cannot delete idt entry\n"); + rtems_fatal_error_occurred(1); + } + + excep_raw_irq_data.on = nop; + excep_raw_irq_data.off = nop; + excep_raw_irq_data.isOn = isOn; + excep_raw_irq_data.hdl = handler; + + if (!i386_set_idt_entry (&excep_raw_irq_data)) { + printk("raw exception handler connection failed\n"); + rtems_fatal_error_occurred(1); + } + return; +} + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/c/src/lib/libbsp/i386/shared/comm/i386-stub.c b/c/src/lib/libbsp/i386/shared/comm/i386-stub.c new file mode 100644 index 0000000000..d4fd60ad9b --- /dev/null +++ b/c/src/lib/libbsp/i386/shared/comm/i386-stub.c @@ -0,0 +1,937 @@ +/* + * This is the gdb i386 remote debug stub from gdb 4.XX. + * + * $Id$ + */ + +/**************************************************************************** + + THIS SOFTWARE IS NOT COPYRIGHTED + + HP offers the following for use in the public domain. HP makes no + warranty with regard to the software or it's performance and the + user accepts the software "AS IS" with all faults. + + HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD + TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES + OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + + ****************************************************************************/ + +/**************************************************************************** + * Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $ + * + * Module name: remcom.c $ + * Revision: 1.34 $ + * Date: 91/03/09 12:29:49 $ + * Contributor: Lake Stevens Instrument Division$ + * + * Description: low level support for gdb debugger. $ + * + * Considerations: only works on target hardware $ + * + * Written by: Glenn Engel $ + * ModuleState: Experimental $ + * + * NOTES: See Below $ + * + * Modified for 386 by Jim Kingdon, Cygnus Support. + * Modified for RTEMS by Aleksey Romanov, Quality Quorum, Inc. + * + * To enable debugger support, two things need to happen. One, a + * call to set_debug_traps() is necessary in order to allow any breakpoints + * or error conditions to be properly intercepted and reported to gdb. + * Two, a breakpoint needs to be generated to begin communication. This + * is most easily accomplished by a call to breakpoint(). Breakpoint() + * simulates a breakpoint by executing a trap #1. + * + * The external function exceptionHandler() is + * used to attach a specific handler to a specific 386 vector number. + * It should use the same privilege level it runs at. It should + * install it as an interrupt gate so that interrupts are masked + * while the handler runs. + * Also, need to assign exceptionHook and oldExceptionHook. + * + * Because gdb will sometimes write to the stack area to execute function + * calls, this program cannot rely on using the supervisor stack so it + * uses it's own stack area reserved in the int array remcomStack. + * + ************* + * + * The following gdb commands are supported: + * + * command function Return value + * + * g return the value of the CPU registers hex data or ENN + * G set the value of the CPU registers OK or ENN + * + * mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN + * MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN + * + * c Resume at current address SNN ( signal NN) + * cAA..AA Continue at address AA..AA SNN + * + * s Step one instruction SNN + * sAA..AA Step one instruction from AA..AA SNN + * + * k kill + * + * ? What was the last sigval ? SNN (signal NN) + * + * All commands and responses are sent with a packet which includes a + * checksum. A packet consists of + * + * $<packet info>#<checksum>. + * + * where + * <packet info> :: <characters representing the command or response> + * <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>> + * + * When a packet is received, it is first acknowledged with either '+' or '-'. + * '+' indicates a successful transfer. '-' indicates a failed transfer. + * + * Example: + * + * Host: Reply: + * $m0,10#2a +$00010203040506070809101112131415#42 + * + ****************************************************************************/ + +#include <stdio.h> +#include <string.h> + +/************************************************************************ + * + * external low-level support routines + */ +extern int putDebugChar (int ch); /* write a single character */ +extern int getDebugChar (void); /* read and return a single char */ + +/* assign an exception handler */ +extern void exceptionHandler (int, void (*handler) (void)); + +/************************************************************************/ +/* BUFMAX defines the maximum number of characters in inbound/outbound buffers */ +/* at least NUMREGBYTES*2 are needed for register packets */ +#define BUFMAX 400 + +static char initialized; /* boolean flag. != 0 means we've been initialized */ + +int remote_debug; +/* debug > 0 prints ill-formed commands in valid packets & checksum errors */ + +void waitabit (); + +static const char hexchars[] = "0123456789abcdef"; + +/* Number of bytes of registers. */ +#define NUMREGBYTES 64 +enum regnames + { + EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI, + PC /* also known as eip */ , + PS /* also known as eflags */ , + CS, SS, DS, ES, FS, GS + }; + +/* + * these should not be static cuz they can be used outside this module + */ +int registers[NUMREGBYTES / 4]; + +#define STACKSIZE 10000 +int remcomStack[STACKSIZE / sizeof (int)]; +static int *stackPtr = &remcomStack[STACKSIZE / sizeof (int) - 1]; + +/*************************** ASSEMBLY CODE MACROS *************************/ +/* */ + +extern void + return_to_prog (void); + +/* Restore the program's registers (including the stack pointer, which + means we get the right stack and don't have to worry about popping our + return address and any stack frames and so on) and return. */ +asm (".text"); +asm (".globl return_to_prog"); +asm ("return_to_prog:"); +asm (" movw registers+44, %ss"); +asm (" movl registers+16, %esp"); +asm (" movl registers+4, %ecx"); +asm (" movl registers+8, %edx"); +asm (" movl registers+12, %ebx"); +asm (" movl registers+20, %ebp"); +asm (" movl registers+24, %esi"); +asm (" movl registers+28, %edi"); +asm (" movw registers+48, %ds"); +asm (" movw registers+52, %es"); +asm (" movw registers+56, %fs"); +asm (" movw registers+60, %gs"); +asm (" movl registers+36, %eax"); +asm (" pushl %eax"); /* saved eflags */ +asm (" movl registers+40, %eax"); +asm (" pushl %eax"); /* saved cs */ +asm (" movl registers+32, %eax"); +asm (" pushl %eax"); /* saved eip */ +asm (" movl registers, %eax"); +/* use iret to restore pc and flags together so + that trace flag works right. */ +asm (" iret"); + +#define BREAKPOINT() asm(" int $3"); + +/* Put the error code here just in case the user cares. */ +int gdb_i386errcode; +/* Likewise, the vector number here (since GDB only gets the signal + number through the usual means, and that's not very specific). */ +int gdb_i386vector = -1; + +/* GDB stores segment registers in 32-bit words (that's just the way + m-i386v.h is written). So zero the appropriate areas in registers. */ +#define SAVE_REGISTERS1() \ + asm ("movl %eax, registers"); \ + asm ("movl %ecx, registers+4"); \ + asm ("movl %edx, registers+8"); \ + asm ("movl %ebx, registers+12"); \ + asm ("movl %ebp, registers+20"); \ + asm ("movl %esi, registers+24"); \ + asm ("movl %edi, registers+28"); \ + asm ("movw $0, %ax"); \ + asm ("movw %ds, registers+48"); \ + asm ("movw %ax, registers+50"); \ + asm ("movw %es, registers+52"); \ + asm ("movw %ax, registers+54"); \ + asm ("movw %fs, registers+56"); \ + asm ("movw %ax, registers+58"); \ + asm ("movw %gs, registers+60"); \ + asm ("movw %ax, registers+62"); +#define SAVE_ERRCODE() \ + asm ("popl %ebx"); \ + asm ("movl %ebx, gdb_i386errcode"); +#define SAVE_REGISTERS2() \ + asm ("popl %ebx"); /* old eip */ \ + asm ("movl %ebx, registers+32"); \ + asm ("popl %ebx"); /* old cs */ \ + asm ("movl %ebx, registers+40"); \ + asm ("movw %ax, registers+42"); \ + asm ("popl %ebx"); /* old eflags */ \ + asm ("movl %ebx, registers+36"); \ + /* Now that we've done the pops, we can save the stack pointer."); */ \ + asm ("movw %ss, registers+44"); \ + asm ("movw %ax, registers+46"); \ + asm ("movl %esp, registers+16"); + +/* See if mem_fault_routine is set, if so just IRET to that address. */ +#define CHECK_FAULT() \ + asm ("cmpl $0, mem_fault_routine"); \ + asm ("jne mem_fault"); + +asm (".text"); +asm ("mem_fault:"); +/* OK to clobber temp registers; we're just going to end up in set_mem_err. */ +/* Pop error code from the stack and save it. */ +asm (" popl %eax"); +asm (" movl %eax, gdb_i386errcode"); + +asm (" popl %eax"); /* eip */ +/* We don't want to return there, we want to return to the function + pointed to by mem_fault_routine instead. */ +asm (" movl mem_fault_routine, %eax"); +asm (" popl %ecx"); /* cs (low 16 bits; junk in hi 16 bits). */ +asm (" popl %edx"); /* eflags */ + +/* Remove this stack frame; when we do the iret, we will be going to + the start of a function, so we want the stack to look just like it + would after a "call" instruction. */ +asm (" leave"); + +/* Push the stuff that iret wants. */ +asm (" pushl %edx"); /* eflags */ +asm (" pushl %ecx"); /* cs */ +asm (" pushl %eax"); /* eip */ + +/* Zero mem_fault_routine. */ +asm (" movl $0, %eax"); +asm (" movl %eax, mem_fault_routine"); + +asm ("iret"); + +#define CALL_HOOK() asm("call _remcomHandler"); + +/* This function is called when a i386 exception occurs. It saves + * all the cpu regs in the registers array, munges the stack a bit, + * and invokes an exception handler (remcom_handler). + * + * stack on entry: stack on exit: + * old eflags vector number + * old cs (zero-filled to 32 bits) + * old eip + * + */ +extern void _catchException3 (); +asm (".text"); +asm (".globl _catchException3"); +asm ("_catchException3:"); +SAVE_REGISTERS1 (); +SAVE_REGISTERS2 (); +asm ("pushl $3"); +CALL_HOOK (); + +/* Same thing for exception 1. */ +extern void _catchException1 (); +asm (".text"); +asm (".globl _catchException1"); +asm ("_catchException1:"); +SAVE_REGISTERS1 (); +SAVE_REGISTERS2 (); +asm ("pushl $1"); +CALL_HOOK (); + +/* Same thing for exception 0. */ +extern void _catchException0 (); +asm (".text"); +asm (".globl _catchException0"); +asm ("_catchException0:"); +SAVE_REGISTERS1 (); +SAVE_REGISTERS2 (); +asm ("pushl $0"); +CALL_HOOK (); + +/* Same thing for exception 4. */ +extern void _catchException4 (); +asm (".text"); +asm (".globl _catchException4"); +asm ("_catchException4:"); +SAVE_REGISTERS1 (); +SAVE_REGISTERS2 (); +asm ("pushl $4"); +CALL_HOOK (); + +/* Same thing for exception 5. */ +extern void _catchException5 (); +asm (".text"); +asm (".globl _catchException5"); +asm ("_catchException5:"); +SAVE_REGISTERS1 (); +SAVE_REGISTERS2 (); +asm ("pushl $5"); +CALL_HOOK (); + +/* Same thing for exception 6. */ +extern void _catchException6 (); +asm (".text"); +asm (".globl _catchException6"); +asm ("_catchException6:"); +SAVE_REGISTERS1 (); +SAVE_REGISTERS2 (); +asm ("pushl $6"); +CALL_HOOK (); + +/* Same thing for exception 7. */ +extern void _catchException7 (); +asm (".text"); +asm (".globl _catchException7"); +asm ("_catchException7:"); +SAVE_REGISTERS1 (); +SAVE_REGISTERS2 (); +asm ("pushl $7"); +CALL_HOOK (); + +/* Same thing for exception 8. */ +extern void _catchException8 (); +asm (".text"); +asm (".globl _catchException8"); +asm ("_catchException8:"); +SAVE_REGISTERS1 (); +SAVE_ERRCODE (); +SAVE_REGISTERS2 (); +asm ("pushl $8"); +CALL_HOOK (); + +/* Same thing for exception 9. */ +extern void _catchException9 (); +asm (".text"); +asm (".globl _catchException9"); +asm ("_catchException9:"); +SAVE_REGISTERS1 (); +SAVE_REGISTERS2 (); +asm ("pushl $9"); +CALL_HOOK (); + +/* Same thing for exception 10. */ +extern void _catchException10 (); +asm (".text"); +asm (".globl _catchException10"); +asm ("_catchException10:"); +SAVE_REGISTERS1 (); +SAVE_ERRCODE (); +SAVE_REGISTERS2 (); +asm ("pushl $10"); +CALL_HOOK (); + +/* Same thing for exception 12. */ +extern void _catchException12 (); +asm (".text"); +asm (".globl _catchException12"); +asm ("_catchException12:"); +SAVE_REGISTERS1 (); +SAVE_ERRCODE (); +SAVE_REGISTERS2 (); +asm ("pushl $12"); +CALL_HOOK (); + +/* Same thing for exception 16. */ +extern void _catchException16 (); +asm (".text"); +asm (".globl _catchException16"); +asm ("_catchException16:"); +SAVE_REGISTERS1 (); +SAVE_REGISTERS2 (); +asm ("pushl $16"); +CALL_HOOK (); + +/* For 13, 11, and 14 we have to deal with the CHECK_FAULT stuff. */ + +/* Same thing for exception 13. */ +extern void _catchException13 (); +asm (".text"); +asm (".globl _catchException13"); +asm ("_catchException13:"); +CHECK_FAULT (); +SAVE_REGISTERS1 (); +SAVE_ERRCODE (); +SAVE_REGISTERS2 (); +asm ("pushl $13"); +CALL_HOOK (); + +/* Same thing for exception 11. */ +extern void _catchException11 (); +asm (".text"); +asm (".globl _catchException11"); +asm ("_catchException11:"); +CHECK_FAULT (); +SAVE_REGISTERS1 (); +SAVE_ERRCODE (); +SAVE_REGISTERS2 (); +asm ("pushl $11"); +CALL_HOOK (); + +/* Same thing for exception 14. */ +extern void _catchException14 (); +asm (".text"); +asm (".globl _catchException14"); +asm ("_catchException14:"); +CHECK_FAULT (); +SAVE_REGISTERS1 (); +SAVE_ERRCODE (); +SAVE_REGISTERS2 (); +asm ("pushl $14"); +CALL_HOOK (); + +/* + * remcomHandler is a front end for handle_exception. It moves the + * stack pointer into an area reserved for debugger use. + */ +asm ("_remcomHandler:"); +asm (" popl %eax"); /* pop off return address */ +asm (" popl %eax"); /* get the exception number */ +asm (" movl stackPtr, %esp"); /* move to remcom stack area */ +asm (" pushl %eax"); /* push exception onto stack */ +asm (" call handle_exception"); /* this never returns */ + +void +_returnFromException (void) +{ + return_to_prog (); +} + +int +hex (char ch) +{ + if ((ch >= 'a') && (ch <= 'f')) + return (ch - 'a' + 10); + if ((ch >= '0') && (ch <= '9')) + return (ch - '0'); + if ((ch >= 'A') && (ch <= 'F')) + return (ch - 'A' + 10); + return (-1); +} + + +/* scan for the sequence $<data>#<checksum> */ +void +getpacket (char *buffer) +{ + unsigned char checksum; + unsigned char xmitcsum; + int i; + int count; + char ch; + + do + { + /* wait around for the start character, ignore all other characters */ + while ((ch = (getDebugChar () & 0x7f)) != '$'); + checksum = 0; + xmitcsum = -1; + + count = 0; + + /* now, read until a # or end of buffer is found */ + while (count < BUFMAX) + { + ch = getDebugChar () & 0x7f; + if (ch == '#') + break; + checksum = checksum + ch; + buffer[count] = ch; + count = count + 1; + } + buffer[count] = 0; + + if (ch == '#') + { + xmitcsum = hex (getDebugChar () & 0x7f) << 4; + xmitcsum += hex (getDebugChar () & 0x7f); + if ((remote_debug) && (checksum != xmitcsum)) + { + fprintf (stderr, "bad checksum. My count = 0x%x, sent=0x%x. buf=%s\n", + checksum, xmitcsum, buffer); + } + + if (checksum != xmitcsum) + putDebugChar ('-'); /* failed checksum */ + else + { + putDebugChar ('+'); /* successful transfer */ + /* if a sequence char is present, reply the sequence ID */ + if (buffer[2] == ':') + { + putDebugChar (buffer[0]); + putDebugChar (buffer[1]); + /* remove sequence chars from buffer */ + count = strlen (buffer); + for (i = 3; i <= count; i++) + buffer[i - 3] = buffer[i]; + } + } + } + } + while (checksum != xmitcsum); + +} + +/* send the packet in buffer. */ + + +void +putpacket (char *buffer) +{ + unsigned char checksum; + int count; + char ch; + + /* $<packet info>#<checksum>. */ + do + { + putDebugChar ('$'); + checksum = 0; + count = 0; + + while ((ch = buffer[count])) + { + if (!putDebugChar (ch)) + return; + checksum += ch; + count += 1; + } + + putDebugChar ('#'); + putDebugChar (hexchars[checksum >> 4]); + putDebugChar (hexchars[checksum % 16]); + + } + while ((getDebugChar () & 0x7f) != '+'); + +} + +char remcomInBuffer[BUFMAX]; +char remcomOutBuffer[BUFMAX]; +static short error; + +void +debug_error (format, parm) + char *format; + char *parm; +{ + if (remote_debug) + fprintf (stderr, format, parm); +} + +/* Address of a routine to RTE to if we get a memory fault. */ +static void (*volatile mem_fault_routine) (void) = NULL; + +/* Indicate to caller of mem2hex or hex2mem that there has been an + error. */ +static volatile int mem_err = 0; + +void +set_mem_err (void) +{ + mem_err = 1; +} + +/* These are separate functions so that they are so short and sweet + that the compiler won't save any registers (if there is a fault + to mem_fault, they won't get restored, so there better not be any + saved). */ +int +get_char (char *addr) +{ + return *addr; +} + +void +set_char (char *addr, int val) +{ + *addr = val; +} + +/* convert the memory pointed to by mem into hex, placing result in buf */ +/* return a pointer to the last char put in buf (null) */ +/* If MAY_FAULT is non-zero, then we should set mem_err in response to + a fault; if zero treat a fault like any other fault in the stub. */ +char * +mem2hex (char *mem, char *buf, int count, int may_fault) +{ + int i; + unsigned char ch; + + if (may_fault) + mem_fault_routine = set_mem_err; + for (i = 0; i < count; i++) + { + ch = get_char (mem++); + if (may_fault && mem_err) + return (buf); + *buf++ = hexchars[ch >> 4]; + *buf++ = hexchars[ch % 16]; + } + *buf = 0; + if (may_fault) + mem_fault_routine = NULL; + return (buf); +} + +/* convert the hex array pointed to by buf into binary to be placed in mem */ +/* return a pointer to the character AFTER the last byte written */ +char * +hex2mem (char *buf, char *mem, int count, int may_fault) +{ + int i; + unsigned char ch; + + if (may_fault) + mem_fault_routine = set_mem_err; + for (i = 0; i < count; i++) + { + ch = hex (*buf++) << 4; + ch = ch + hex (*buf++); + set_char (mem++, ch); + if (may_fault && mem_err) + return (mem); + } + if (may_fault) + mem_fault_routine = NULL; + return (mem); +} + +/* this function takes the 386 exception vector and attempts to + translate this number into a unix compatible signal value */ +int +computeSignal (int exceptionVector) +{ + int sigval; + switch (exceptionVector) + { + case 0: + sigval = 8; + break; /* divide by zero */ + case 1: + sigval = 5; + break; /* debug exception */ + case 3: + sigval = 5; + break; /* breakpoint */ + case 4: + sigval = 16; + break; /* into instruction (overflow) */ + case 5: + sigval = 16; + break; /* bound instruction */ + case 6: + sigval = 4; + break; /* Invalid opcode */ + case 7: + sigval = 8; + break; /* coprocessor not available */ + case 8: + sigval = 7; + break; /* double fault */ + case 9: + sigval = 11; + break; /* coprocessor segment overrun */ + case 10: + sigval = 11; + break; /* Invalid TSS */ + case 11: + sigval = 11; + break; /* Segment not present */ + case 12: + sigval = 11; + break; /* stack exception */ + case 13: + sigval = 11; + break; /* general protection */ + case 14: + sigval = 11; + break; /* page fault */ + case 16: + sigval = 7; + break; /* coprocessor error */ + default: + sigval = 7; /* "software generated" */ + } + return (sigval); +} + +/**********************************************/ +/* WHILE WE FIND NICE HEX CHARS, BUILD AN INT */ +/* RETURN NUMBER OF CHARS PROCESSED */ +/**********************************************/ +int +hexToInt (char **ptr, int *intValue) +{ + int numChars = 0; + int hexValue; + + *intValue = 0; + + while (**ptr) + { + hexValue = hex (**ptr); + if (hexValue >= 0) + { + *intValue = (*intValue << 4) | hexValue; + numChars++; + } + else + break; + + (*ptr)++; + } + + return (numChars); +} + +/* + * This function does all command procesing for interfacing to gdb. + */ +void +handle_exception (int exceptionVector) +{ + int sigval; + int addr, length; + char *ptr; + int newPC; + + gdb_i386vector = exceptionVector; + + if (remote_debug) + printf ("vector=%d, sr=0x%x, pc=0x%x\n", + exceptionVector, + registers[PS], + registers[PC]); + + /* reply to host that an exception has occurred */ + sigval = computeSignal (exceptionVector); + remcomOutBuffer[0] = 'S'; + remcomOutBuffer[1] = hexchars[sigval >> 4]; + remcomOutBuffer[2] = hexchars[sigval % 16]; + remcomOutBuffer[3] = 0; + + putpacket (remcomOutBuffer); + + while (1 == 1) + { + error = 0; + remcomOutBuffer[0] = 0; + getpacket (remcomInBuffer); + switch (remcomInBuffer[0]) + { + case '?': + remcomOutBuffer[0] = 'S'; + remcomOutBuffer[1] = hexchars[sigval >> 4]; + remcomOutBuffer[2] = hexchars[sigval % 16]; + remcomOutBuffer[3] = 0; + break; + case 'd': + remote_debug = !(remote_debug); /* toggle debug flag */ + break; + case 'g': /* return the value of the CPU registers */ + mem2hex ((char *) registers, remcomOutBuffer, NUMREGBYTES, 0); + break; + case 'G': /* set the value of the CPU registers - return OK */ + hex2mem (&remcomInBuffer[1], (char *) registers, NUMREGBYTES, 0); + strcpy (remcomOutBuffer, "OK"); + break; + + /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */ + case 'm': + /* TRY TO READ %x,%x. IF SUCCEED, SET PTR = 0 */ + ptr = &remcomInBuffer[1]; + if (hexToInt (&ptr, &addr)) + if (*(ptr++) == ',') + if (hexToInt (&ptr, &length)) + { + ptr = 0; + mem_err = 0; + mem2hex ((char *) addr, remcomOutBuffer, length, 1); + if (mem_err) + { + strcpy (remcomOutBuffer, "E03"); + debug_error ("memory fault"); + } + } + + if (ptr) + { + strcpy (remcomOutBuffer, "E01"); + debug_error ("malformed read memory command: %s", remcomInBuffer); + } + break; + + /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */ + case 'M': + /* TRY TO READ '%x,%x:'. IF SUCCEED, SET PTR = 0 */ + ptr = &remcomInBuffer[1]; + if (hexToInt (&ptr, &addr)) + if (*(ptr++) == ',') + if (hexToInt (&ptr, &length)) + if (*(ptr++) == ':') + { + mem_err = 0; + hex2mem (ptr, (char *) addr, length, 1); + + if (mem_err) + { + strcpy (remcomOutBuffer, "E03"); + debug_error ("memory fault"); + } + else + { + strcpy (remcomOutBuffer, "OK"); + } + + ptr = 0; + } + if (ptr) + { + strcpy (remcomOutBuffer, "E02"); + debug_error ("malformed write memory command: %s", remcomInBuffer); + } + break; + + /* cAA..AA Continue at address AA..AA(optional) */ + /* sAA..AA Step one instruction from AA..AA(optional) */ + case 'c': + case 's': + /* try to read optional parameter, pc unchanged if no parm */ + ptr = &remcomInBuffer[1]; + if (hexToInt (&ptr, &addr)) + registers[PC] = addr; + + newPC = registers[PC]; + + /* clear the trace bit */ + registers[PS] &= 0xfffffeff; + + /* set the trace bit if we're stepping */ + if (remcomInBuffer[0] == 's') + registers[PS] |= 0x100; + + _returnFromException (); /* this is a jump */ + + break; + + /* kill the program */ + case 'k': /* do nothing */ + break; + } /* switch */ + + /* reply to the request */ + putpacket (remcomOutBuffer); + } +} + +/* this function is used to set up exception handlers for tracing and + breakpoints */ +void +set_debug_traps (void) +{ + extern void remcomHandler (); + + stackPtr = &remcomStack[STACKSIZE / sizeof (int) - 1]; + + exceptionHandler (0, _catchException0); + exceptionHandler (1, _catchException1); + exceptionHandler (3, _catchException3); + exceptionHandler (4, _catchException4); + exceptionHandler (5, _catchException5); + exceptionHandler (6, _catchException6); + exceptionHandler (7, _catchException7); + exceptionHandler (8, _catchException8); + exceptionHandler (9, _catchException9); + exceptionHandler (10, _catchException10); + exceptionHandler (11, _catchException11); + exceptionHandler (12, _catchException12); + exceptionHandler (13, _catchException13); + exceptionHandler (14, _catchException14); + exceptionHandler (16, _catchException16); + + /* In case GDB is started before us, ack any packets (presumably + "$?#xx") sitting there. */ + putDebugChar ('+'); + + initialized = 1; + +} + +/* This function will generate a breakpoint exception. It is used at the + beginning of a program to sync up with a debugger and can be used + otherwise as a quick means to stop program execution and "break" into + the debugger. */ + +void +breakpoint (void) +{ + if (initialized) + { + BREAKPOINT (); + } + waitabit (); +} + +int waitlimit = 1000000; + +void +waitabit (void) +{ + int i; + for (i = 0; i < waitlimit; i++); +} + + + + + diff --git a/c/src/lib/libbsp/i386/shared/comm/uart.c b/c/src/lib/libbsp/i386/shared/comm/uart.c new file mode 100644 index 0000000000..5d258d7232 --- /dev/null +++ b/c/src/lib/libbsp/i386/shared/comm/uart.c @@ -0,0 +1,935 @@ +/* + * This software is Copyright (C) 1998 by T.sqware - all rights limited + * It is provided in to the public domain "as is", can be freely modified + * as far as this copyight notice is kept unchanged, but does not imply + * an endorsement by T.sqware of the product in which it is included. + * + * $Id$ + */ + +#include <bsp.h> +#include <irq.h> +#include <uart.h> +#include <rtems/libio.h> +#include <assert.h> + +/* + * Basic 16552 driver + */ + +struct uart_data +{ + int hwFlow; + int baud; +}; + +static struct uart_data uart_data[2]; + +/* + * Macros to read/wirte register of uart, if configuration is + * different just rewrite these macros + */ + +static inline unsigned char +uread(int uart, unsigned int reg) +{ + register unsigned char val; + + if(uart == 0) + { + i386_inport_byte(COM1_BASE_IO+reg, val); + } + else + { + i386_inport_byte(COM2_BASE_IO+reg, val); + } + + return val; +} + +static inline void +uwrite(int uart, int reg, unsigned int val) +{ + if(uart == 0) + { + i386_outport_byte(COM1_BASE_IO+reg, val); + } + else + { + i386_outport_byte(COM2_BASE_IO+reg, val); + } +} + +#ifdef UARTDEBUG + static void +uartError(int uart) +{ + unsigned char uartStatus, dummy; + + uartStatus = uread(uart, LSR); + dummy = uread(uart, RBR); + + if (uartStatus & OE) + printk("********* Over run Error **********\n"); + if (uartStatus & PE) + printk("********* Parity Error **********\n"); + if (uartStatus & FE) + printk("********* Framing Error **********\n"); + if (uartStatus & BI) + printk("********* Parity Error **********\n"); + if (uartStatus & ERFIFO) + printk("********* Error receive Fifo **********\n"); + +} +#else +inline void uartError(int uart) +{ + unsigned char uartStatus; + + uartStatus = uread(uart, LSR); + uartStatus = uread(uart, RBR); +} +#endif + +/* + * Uart initialization, it is hardcoded to 8 bit, no parity, + * one stop bit, FIFO, things to be changed + * are baud rate and nad hw flow control, + * and longest rx fifo setting + */ +void +BSP_uart_init(int uart, int baud, int hwFlow) +{ + unsigned char tmp; + + /* Sanity check */ + assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2); + + switch(baud) + { + case 50: + case 75: + case 110: + case 134: + case 300: + case 600: + case 1200: + case 2400: + case 9600: + case 19200: + case 38400: + case 57600: + case 115200: + break; + default: + assert(0); + return; + } + + /* Set DLAB bit to 1 */ + uwrite(uart, LCR, DLAB); + + /* Set baud rate */ + uwrite(uart, DLL, (BSPBaseBaud/baud) & 0xff); + uwrite(uart, DLM, ((BSPBaseBaud/baud) >> 8) & 0xff); + + /* 8-bit, no parity , 1 stop */ + uwrite(uart, LCR, CHR_8_BITS); + + + /* Set DTR, RTS and OUT2 high */ + uwrite(uart, MCR, DTR | RTS | OUT_2); + + /* Enable FIFO */ + uwrite(uart, FCR, FIFO_EN | XMIT_RESET | RCV_RESET | RECEIVE_FIFO_TRIGGER12); + + /* Disable Interrupts */ + uwrite(uart, IER, 0); + + /* Read status to clear them */ + tmp = uread(uart, LSR); + tmp = uread(uart, RBR); + tmp = uread(uart, MSR); + + /* Remember state */ + uart_data[uart].hwFlow = hwFlow; + uart_data[uart].baud = baud; + return; +} + +/* + * Set baud + */ +void +BSP_uart_set_baud(int uart, int baud) +{ + unsigned char mcr, ier; + + /* Sanity check */ + assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2); + + /* + * This function may be called whenever TERMIOS parameters + * are changed, so we have to make sire that baud change is + * indeed required + */ + + if(baud == uart_data[uart].baud) + { + return; + } + + mcr = uread(uart, MCR); + ier = uread(uart, IER); + + BSP_uart_init(uart, baud, uart_data[uart].hwFlow); + + uwrite(uart, MCR, mcr); + uwrite(uart, IER, ier); + + return; +} + +/* + * Enable/disable interrupts + */ +void +BSP_uart_intr_ctrl(int uart, int cmd) +{ + + assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2); + + switch(cmd) + { + case BSP_UART_INTR_CTRL_DISABLE: + uwrite(uart, IER, INTERRUPT_DISABLE); + break; + case BSP_UART_INTR_CTRL_ENABLE: + if(uart_data[uart].hwFlow) + { + uwrite(uart, IER, + (RECEIVE_ENABLE | + TRANSMIT_ENABLE | + RECEIVER_LINE_ST_ENABLE | + MODEM_ENABLE + ) + ); + } + else + { + uwrite(uart, IER, + (RECEIVE_ENABLE | + TRANSMIT_ENABLE | + RECEIVER_LINE_ST_ENABLE + ) + ); + } + break; + case BSP_UART_INTR_CTRL_TERMIOS: + if(uart_data[uart].hwFlow) + { + uwrite(uart, IER, + (RECEIVE_ENABLE | + RECEIVER_LINE_ST_ENABLE | + MODEM_ENABLE + ) + ); + } + else + { + uwrite(uart, IER, + (RECEIVE_ENABLE | + RECEIVER_LINE_ST_ENABLE + ) + ); + } + break; + case BSP_UART_INTR_CTRL_GDB: + uwrite(uart, IER, RECEIVE_ENABLE); + break; + default: + assert(0); + break; + } + + return; +} + +void +BSP_uart_throttle(int uart) +{ + unsigned int mcr; + + assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2); + + if(!uart_data[uart].hwFlow) + { + /* Should not happen */ + assert(0); + return; + } + mcr = uread (uart, MCR); + /* RTS down */ + mcr &= ~RTS; + uwrite(uart, MCR, mcr); + + return; +} + +void +BSP_uart_unthrottle(int uart) +{ + unsigned int mcr; + + assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2); + + if(!uart_data[uart].hwFlow) + { + /* Should not happen */ + assert(0); + return; + } + mcr = uread (uart, MCR); + /* RTS up */ + mcr |= RTS; + uwrite(uart, MCR, mcr); + + return; +} + +/* + * Status function, -1 if error + * detected, 0 if no received chars available, + * 1 if received char available, 2 if break + * is detected, it will eat break and error + * chars. It ignores overruns - we cannot do + * anything about - it execpt count statistics + * and we are not counting it. + */ +int +BSP_uart_polled_status(int uart) +{ + unsigned char val; + + assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2); + + val = uread(uart, LSR); + + if(val & BI) + { + /* BREAK found, eat character */ + uread(uart, RBR); + return BSP_UART_STATUS_BREAK; + } + + if((val & (DR | OE | FE)) == 1) + { + /* No error, character present */ + return BSP_UART_STATUS_CHAR; + } + + if((val & (DR | OE | FE)) == 0) + { + /* Nothing */ + return BSP_UART_STATUS_NOCHAR; + } + + /* + * Framing or parity error + * eat character + */ + uread(uart, RBR); + + return BSP_UART_STATUS_ERROR; +} + + +/* + * Polled mode write function + */ +void +BSP_uart_polled_write(int uart, int val) +{ + unsigned char val1; + + /* Sanity check */ + assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2); + + for(;;) + { + if((val1=uread(uart, LSR)) & THRE) + { + break; + } + } + + if(uart_data[uart].hwFlow) + { + for(;;) + { + if(uread(uart, MSR) & CTS) + { + break; + } + } + } + + uwrite(uart, THR, val & 0xff); + + return; +} + +void +BSP_output_char_via_serial(int val) +{ + BSP_uart_polled_write(BSPConsolePort, val); + if (val == '\n') BSP_uart_polled_write(BSPConsolePort,'\r'); +} + +/* + * Polled mode read function + */ +int +BSP_uart_polled_read(int uart) +{ + unsigned char val; + + assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2); + + for(;;) + { + if(uread(uart, LSR) & DR) + { + break; + } + } + + val = uread(uart, RBR); + + return (int)(val & 0xff); +} + +unsigned +BSP_poll_char_via_serial() +{ + return BSP_uart_polled_read(BSPConsolePort); +} + + +/* ================ Termios support =================*/ + +static volatile int termios_stopped_com1 = 0; +static volatile int termios_tx_active_com1 = 0; +static void* termios_ttyp_com1 = NULL; +static char termios_tx_hold_com1 = 0; +static volatile char termios_tx_hold_valid_com1 = 0; + +static volatile int termios_stopped_com2 = 0; +static volatile int termios_tx_active_com2 = 0; +static void* termios_ttyp_com2 = NULL; +static char termios_tx_hold_com2 = 0; +static volatile char termios_tx_hold_valid_com2 = 0; + +/* + * Set channel parameters + */ +void +BSP_uart_termios_set(int uart, void *ttyp) +{ + unsigned char val; + assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2); + + if(uart == BSP_UART_COM1) + { + if(uart_data[uart].hwFlow) + { + val = uread(uart, MSR); + + termios_stopped_com1 = (val & CTS) ? 0 : 1; + } + else + { + termios_stopped_com1 = 0; + } + termios_tx_active_com1 = 0; + termios_ttyp_com1 = ttyp; + termios_tx_hold_com1 = 0; + termios_tx_hold_valid_com1 = 0; + } + else + { + if(uart_data[uart].hwFlow) + { + val = uread(uart, MSR); + + termios_stopped_com2 = (val & CTS) ? 0 : 1; + } + else + { + termios_stopped_com2 = 0; + } + termios_tx_active_com2 = 0; + termios_ttyp_com2 = ttyp; + termios_tx_hold_com2 = 0; + termios_tx_hold_valid_com2 = 0; + } + + return; +} + +int +BSP_uart_termios_write_com1(int minor, const char *buf, int len) +{ + assert(buf != NULL); + + if(len <= 0) + { + return 0; + } + + /* If there TX buffer is busy - something is royally screwed up */ + assert((uread(BSP_UART_COM1, LSR) & THRE) != 0); + + if(termios_stopped_com1) + { + /* CTS low */ + termios_tx_hold_com1 = *buf; + termios_tx_hold_valid_com1 = 1; + return 0; + } + + /* Write character */ + uwrite(BSP_UART_COM1, THR, *buf & 0xff); + + /* Enable interrupts if necessary */ + if(!termios_tx_active_com1 && uart_data[BSP_UART_COM1].hwFlow) + { + termios_tx_active_com1 = 1; + uwrite(BSP_UART_COM1, IER, + (RECEIVE_ENABLE | + TRANSMIT_ENABLE | + RECEIVER_LINE_ST_ENABLE | + MODEM_ENABLE + ) + ); + } + else if(!termios_tx_active_com1) + { + termios_tx_active_com1 = 1; + uwrite(BSP_UART_COM1, IER, + (RECEIVE_ENABLE | + TRANSMIT_ENABLE | + RECEIVER_LINE_ST_ENABLE + ) + ); + } + + return 0; +} + +int +BSP_uart_termios_write_com2(int minor, const char *buf, int len) +{ + assert(buf != NULL); + + if(len <= 0) + { + return 0; + } + + + /* If there TX buffer is busy - something is royally screwed up */ + assert((uread(BSP_UART_COM2, LSR) & THRE) != 0); + + if(termios_stopped_com2) + { + /* CTS low */ + termios_tx_hold_com2 = *buf; + termios_tx_hold_valid_com2 = 1; + return 0; + } + + /* Write character */ + + uwrite(BSP_UART_COM2, THR, *buf & 0xff); + + /* Enable interrupts if necessary */ + if(!termios_tx_active_com2 && uart_data[BSP_UART_COM2].hwFlow) + { + termios_tx_active_com2 = 1; + uwrite(BSP_UART_COM2, IER, + (RECEIVE_ENABLE | + TRANSMIT_ENABLE | + RECEIVER_LINE_ST_ENABLE | + MODEM_ENABLE + ) + ); + } + else if(!termios_tx_active_com2) + { + termios_tx_active_com2 = 1; + uwrite(BSP_UART_COM2, IER, + (RECEIVE_ENABLE | + TRANSMIT_ENABLE | + RECEIVER_LINE_ST_ENABLE + ) + ); + } + + return 0; +} + + +void +BSP_uart_termios_isr_com1(void) +{ + unsigned char buf[40]; + unsigned char val; + int off, ret, vect; + + off = 0; + + for(;;) + { + vect = uread(BSP_UART_COM1, IIR) & 0xf; + + switch(vect) + { + case MODEM_STATUS : + val = uread(BSP_UART_COM1, MSR); + if(uart_data[BSP_UART_COM1].hwFlow) + { + if(val & CTS) + { + /* CTS high */ + termios_stopped_com1 = 0; + if(termios_tx_hold_valid_com1) + { + termios_tx_hold_valid_com1 = 0; + BSP_uart_termios_write_com1(0, &termios_tx_hold_com1, + 1); + } + } + else + { + /* CTS low */ + termios_stopped_com1 = 1; + } + } + break; + case NO_MORE_INTR : + /* No more interrupts */ + if(off != 0) + { + /* Update rx buffer */ + rtems_termios_enqueue_raw_characters(termios_ttyp_com1, + (char *)buf, + off); + } + return; + case TRANSMITTER_HODING_REGISTER_EMPTY : + /* + * TX holding empty: we have to disable these interrupts + * if there is nothing more to send. + */ + + ret = rtems_termios_dequeue_characters(termios_ttyp_com1, 1); + + /* If nothing else to send disable interrupts */ + if(ret == 0 && uart_data[BSP_UART_COM1].hwFlow) + { + uwrite(BSP_UART_COM1, IER, + (RECEIVE_ENABLE | + RECEIVER_LINE_ST_ENABLE | + MODEM_ENABLE + ) + ); + termios_tx_active_com1 = 0; + } + else if(ret == 0) + { + uwrite(BSP_UART_COM1, IER, + (RECEIVE_ENABLE | + RECEIVER_LINE_ST_ENABLE + ) + ); + termios_tx_active_com1 = 0; + } + break; + case RECEIVER_DATA_AVAIL : + case CHARACTER_TIMEOUT_INDICATION: + /* RX data ready */ + assert(off < sizeof(buf)); + buf[off++] = uread(BSP_UART_COM1, RBR); + break; + case RECEIVER_ERROR: + /* RX error: eat character */ + uartError(BSP_UART_COM1); + break; + default: + /* Should not happen */ + assert(0); + return; + } + } +} + +void +BSP_uart_termios_isr_com2() +{ + unsigned char buf[40]; + unsigned char val; + int off, ret, vect; + + off = 0; + + for(;;) + { + vect = uread(BSP_UART_COM2, IIR) & 0xf; + + switch(vect) + { + case MODEM_STATUS : + val = uread(BSP_UART_COM2, MSR); + if(uart_data[BSP_UART_COM2].hwFlow) + { + if(val & CTS) + { + /* CTS high */ + termios_stopped_com2 = 0; + if(termios_tx_hold_valid_com2) + { + termios_tx_hold_valid_com2 = 0; + BSP_uart_termios_write_com2(0, &termios_tx_hold_com2, + 1); + } + } + else + { + /* CTS low */ + termios_stopped_com2 = 1; + } + } + break; + case NO_MORE_INTR : + /* No more interrupts */ + if(off != 0) + { + /* Update rx buffer */ + rtems_termios_enqueue_raw_characters(termios_ttyp_com2, + (char *)buf, + off); + } + return; + case TRANSMITTER_HODING_REGISTER_EMPTY : + /* + * TX holding empty: we have to disable these interrupts + * if there is nothing more to send. + */ + + ret = rtems_termios_dequeue_characters(termios_ttyp_com2, 1); + + /* If nothing else to send disable interrupts */ + if(ret == 0 && uart_data[BSP_UART_COM2].hwFlow) + { + uwrite(BSP_UART_COM2, IER, + (RECEIVE_ENABLE | + RECEIVER_LINE_ST_ENABLE | + MODEM_ENABLE + ) + ); + termios_tx_active_com2 = 0; + } + else if(ret == 0) + { + uwrite(BSP_UART_COM2, IER, + (RECEIVE_ENABLE | + RECEIVER_LINE_ST_ENABLE + ) + ); + termios_tx_active_com2 = 0; + } + break; + case RECEIVER_DATA_AVAIL : + case CHARACTER_TIMEOUT_INDICATION: + /* RX data ready */ + assert(off < sizeof(buf)); + buf[off++] = uread(BSP_UART_COM2, RBR); + break; + case RECEIVER_ERROR: + /* RX error: eat character */ + uartError(BSP_UART_COM2); + break; + default: + /* Should not happen */ + assert(0); + return; + } + } +} + + +/* ================= GDB support ===================*/ +static int sav[4]; + +/* + * Interrupt service routine for COM1 - all, + * it does it check whether ^C is received + * if yes it will flip TF bit before returning + * Note: it should be installed as raw interrupt + * handler + */ + +asm (".p2align 4"); +asm (".text"); +asm (".globl BSP_uart_dbgisr_com1"); +asm ("BSP_uart_dbgisr_com1:"); +asm (" movl %eax, sav"); /* Save eax */ +asm (" movl %ebx, sav + 4"); /* Save ebx */ +asm (" movl %edx, sav + 8"); /* Save edx */ + +asm (" movl $0, %ebx"); /* Clear flag */ + +/* + * We know that only receive related interrupts + * are available, eat chars + */ +asm ("uart_dbgisr_com1_1:"); +asm (" movw $0x3FD, %dx"); +asm (" inb %dx, %al"); /* Read LSR */ +asm (" andb $1, %al"); +asm (" cmpb $0, %al"); +asm (" je uart_dbgisr_com1_2"); +asm (" movw $0x3F8, %dx"); +asm (" inb %dx, %al"); /* Get input character */ +asm (" cmpb $3, %al"); +asm (" jne uart_dbgisr_com1_1"); + +/* ^C received, set flag */ +asm (" movl $1, %ebx"); +asm (" jmp uart_dbgisr_com1_1"); + +/* All chars read */ +asm ("uart_dbgisr_com1_2:"); + +/* If flag is set we have to tweak TF */ +asm (" cmpl $0, %ebx"); +asm (" je uart_dbgisr_com1_3"); + +/* Flag is set */ +asm (" movl sav+4, %ebx"); /* Restore ebx */ +asm (" movl sav+8, %edx"); /* Restore edx */ + +/* Set TF bit */ +asm (" popl %eax"); /* Pop eip */ +asm (" movl %eax, sav + 4"); /* Save it */ +asm (" popl %eax"); /* Pop cs */ +asm (" movl %eax, sav + 8"); /* Save it */ +asm (" popl %eax"); /* Pop flags */ +asm (" orl $0x100, %eax"); /* Modify it */ +asm (" pushl %eax"); /* Push it back */ +asm (" movl sav+8, %eax"); /* Put back cs */ +asm (" pushl %eax"); +asm (" movl sav+4, %eax"); /* Put back eip */ +asm (" pushl %eax"); + +/* Acknowledge IRQ */ +asm (" movb $0x20, %al"); +asm (" outb %al, $0x20"); +asm (" movl sav, %eax"); /* Restore eax */ +asm (" iret"); /* Done */ + +/* Flag is not set */ +asm("uart_dbgisr_com1_3:"); +asm (" movl sav+4, %ebx"); /* Restore ebx */ +asm (" movl sav+8, %edx"); /* Restore edx */ + +/* Acknowledge irq */ +asm (" movb $0x20, %al"); +asm (" outb %al, $0x20"); +asm (" movl sav, %eax"); /* Restore eax */ +asm (" iret"); /* Done */ + + +/* + * Interrupt service routine for COM2 - all, + * it does it check whether ^C is received + * if yes it will flip TF bit before returning + * Note: it has to be installed as raw interrupt + * handler + */ +asm (".p2align 4"); +asm (".text"); +asm (".globl BSP_uart_dbgisr_com2"); +asm ("BSP_uart_dbgisr_com2:"); +asm (" movl %eax, sav"); /* Save eax */ +asm (" movl %ebx, sav + 4"); /* Save ebx */ +asm (" movl %edx, sav + 8"); /* Save edx */ + +asm (" movl $0, %ebx"); /* Clear flag */ + +/* + * We know that only receive related interrupts + * are available, eat chars + */ +asm ("uart_dbgisr_com2_1:"); +asm (" movw $0x2FD, %dx"); +asm (" inb %dx, %al"); /* Read LSR */ +asm (" andb $1, %al"); +asm (" cmpb $0, %al"); +asm (" je uart_dbgisr_com2_2"); +asm (" movw $0x2F8, %dx"); +asm (" inb %dx, %al"); /* Get input character */ +asm (" cmpb $3, %al"); +asm (" jne uart_dbgisr_com2_1"); + +/* ^C received, set flag */ +asm (" movl $1, %ebx"); +asm (" jmp uart_dbgisr_com2_1"); + +/* All chars read */ +asm ("uart_dbgisr_com2_2:"); + +/* If flag is set we have to tweak TF */ +asm (" cmpl $0, %ebx"); +asm (" je uart_dbgisr_com2_3"); + +/* Flag is set */ +asm (" movl sav+4, %ebx"); /* Restore ebx */ +asm (" movl sav+8, %edx"); /* Restore edx */ + +/* Set TF bit */ +asm (" popl %eax"); /* Pop eip */ +asm (" movl %eax, sav + 4"); /* Save it */ +asm (" popl %eax"); /* Pop cs */ +asm (" movl %eax, sav + 8"); /* Save it */ +asm (" popl %eax"); /* Pop flags */ +asm (" orl $0x100, %eax"); /* Modify it */ +asm (" pushl %eax"); /* Push it back */ +asm (" movl sav+8, %eax"); /* Put back cs */ +asm (" pushl %eax"); +asm (" movl sav+4, %eax"); /* Put back eip */ +asm (" pushl %eax"); + +/* Acknowledge IRQ */ +asm (" movb $0x20, %al"); +asm (" outb %al, $0x20"); +asm (" movl sav, %eax"); /* Restore eax */ +asm (" iret"); /* Done */ + +/* Flag is not set */ +asm("uart_dbgisr_com2_3:"); +asm (" movl sav+4, %ebx"); /* Restore ebx */ +asm (" movl sav+8, %edx"); /* Restore edx */ + +/* Acknowledge irq */ +asm (" movb $0x20, %al"); +asm (" outb %al, $0x20"); +asm (" movl sav, %eax"); /* Restore eax */ +asm (" iret"); /* Done */ + + + + + + diff --git a/c/src/lib/libbsp/i386/shared/comm/uart.h b/c/src/lib/libbsp/i386/shared/comm/uart.h new file mode 100644 index 0000000000..e43ac9900c --- /dev/null +++ b/c/src/lib/libbsp/i386/shared/comm/uart.h @@ -0,0 +1,169 @@ + + +/* + * This software is Copyright (C) 1998 by T.sqware - all rights limited + * It is provided in to the public domain "as is", can be freely modified + * as far as this copyight notice is kept unchanged, but does not imply + * an endorsement by T.sqware of the product in which it is included. + */ + +#ifndef _BSPUART_H +#define _BSPUART_H + +void BSP_uart_init(int uart, int baud, int hwFlow); +void BSP_uart_set_baud(int aurt, int baud); +void BSP_uart_intr_ctrl(int uart, int cmd); +void BSP_uart_throttle(int uart); +void BSP_uart_unthrottle(int uart); +int BSP_uart_polled_status(int uart); +void BSP_uart_polled_write(int uart, int val); +int BSP_uart_polled_read(int uart); +void BSP_uart_termios_set(int uart, void *ttyp); +int BSP_uart_termios_write_com1(int minor, const char *buf, int len); +int BSP_uart_termios_write_com2(int minor, const char *buf, int len); +void BSP_uart_termios_isr_com1(); +void BSP_uart_termios_isr_com2(); +void BSP_uart_dbgisr_com1(void); +void BSP_uart_dbgisr_com2(void); +extern unsigned BSP_poll_char_via_serial(void); +extern void BSP_output_char_via_serial(int val); +extern int BSPConsolePort; +extern int BSPBaseBaud; +/* + * Command values for BSP_uart_intr_ctrl(), + * values are strange in order to catch errors + * with assert + */ +#define BSP_UART_INTR_CTRL_DISABLE (0) +#define BSP_UART_INTR_CTRL_GDB (0xaa) /* RX only */ +#define BSP_UART_INTR_CTRL_ENABLE (0xbb) /* Normal operations */ +#define BSP_UART_INTR_CTRL_TERMIOS (0xcc) /* RX & line status */ + +/* Return values for uart_polled_status() */ +#define BSP_UART_STATUS_ERROR (-1) /* No character */ +#define BSP_UART_STATUS_NOCHAR (0) /* No character */ +#define BSP_UART_STATUS_CHAR (1) /* Character present */ +#define BSP_UART_STATUS_BREAK (2) /* Break point is detected */ + +/* PC UART definitions */ +#define BSP_UART_COM1 (0) +#define BSP_UART_COM2 (1) + +/* + * Base IO for UART + */ + +#define COM1_BASE_IO 0x3F8 +#define COM2_BASE_IO 0x2F8 + +/* + * Offsets from base + */ + +/* DLAB 0 */ +#define RBR (0) /* Rx Buffer Register (read) */ +#define THR (0) /* Tx Buffer Register (write) */ +#define IER (1) /* Interrupt Enable Register */ + +/* DLAB X */ +#define IIR (2) /* Interrupt Ident Register (read) */ +#define FCR (2) /* FIFO Control Register (write) */ +#define LCR (3) /* Line Control Register */ +#define MCR (4) /* Modem Control Register */ +#define LSR (5) /* Line Status Register */ +#define MSR (6) /* Modem Status Register */ +#define SCR (7) /* Scratch register */ + +/* DLAB 1 */ +#define DLL (0) /* Divisor Latch, LSB */ +#define DLM (1) /* Divisor Latch, MSB */ +#define AFR (2) /* Alternate Function register */ + +/* + * Interrupt source definition via IIR + */ +#define MODEM_STATUS 0 +#define NO_MORE_INTR 1 +#define TRANSMITTER_HODING_REGISTER_EMPTY 2 +#define RECEIVER_DATA_AVAIL 4 +#define RECEIVER_ERROR 6 +#define CHARACTER_TIMEOUT_INDICATION 12 + +/* + * Bits definition of IER + */ +#define RECEIVE_ENABLE 0x1 +#define TRANSMIT_ENABLE 0x2 +#define RECEIVER_LINE_ST_ENABLE 0x4 +#define MODEM_ENABLE 0x8 +#define INTERRUPT_DISABLE 0x0 + +/* + * Bits definition of the Line Status Register (LSR) + */ +#define DR 0x01 /* Data Ready */ +#define OE 0x02 /* Overrun Error */ +#define PE 0x04 /* Parity Error */ +#define FE 0x08 /* Framing Error */ +#define BI 0x10 /* Break Interrupt */ +#define THRE 0x20 /* Transmitter Holding Register Empty */ +#define TEMT 0x40 /* Transmitter Empty */ +#define ERFIFO 0x80 /* Error receive Fifo */ + +/* + * Bits definition of the MODEM Control Register (MCR) + */ +#define DTR 0x01 /* Data Terminal Ready */ +#define RTS 0x02 /* Request To Send */ +#define OUT_1 0x04 /* Output 1, (reserved on COMPAQ I/O Board) */ +#define OUT_2 0x08 /* Output 2, Enable Asynchronous Port Interrupts */ +#define LB 0x10 /* Enable Internal Loop Back */ + +/* + * Bits definition of the Line Control Register (LCR) + */ +#define CHR_5_BITS 0 +#define CHR_6_BITS 1 +#define CHR_7_BITS 2 +#define CHR_8_BITS 3 + +#define WL 0x03 /* Word length mask */ +#define STB 0x04 /* 1 Stop Bit, otherwise 2 Stop Bits */ +#define PEN 0x08 /* Parity Enabled */ +#define EPS 0x10 /* Even Parity Select, otherwise Odd */ +#define SP 0x20 /* Stick Parity */ +#define BCB 0x40 /* Break Control Bit */ +#define DLAB 0x80 /* Enable Divisor Latch Access */ + +/* + * Bits definition of the MODEM Status Register (MSR) + */ +#define DCTS 0x01 /* Delta Clear To Send */ +#define DDSR 0x02 /* Delta Data Set Ready */ +#define TERI 0x04 /* Trailing Edge Ring Indicator */ +#define DDCD 0x08 /* Delta Carrier Detect Indicator */ +#define CTS 0x10 /* Clear To Send (when loop back is active) */ +#define DSR 0x20 /* Data Set Ready (when loop back is active) */ +#define RI 0x40 /* Ring Indicator (when loop back is active) */ +#define DCD 0x80 /* Data Carrier Detect (when loop back is active) */ + +/* + * Bits definition of the FIFO Control Register : WD16C552 or NS16550 + */ + +#define FIFO_CTRL 0x01 /* Set to 1 permit access to other bits */ +#define FIFO_EN 0x01 /* Enable the FIFO */ +#define XMIT_RESET 0x02 /* Transmit FIFO Reset */ +#define RCV_RESET 0x04 /* Receive FIFO Reset */ +#define FCR3 0x08 /* do not understand manual! */ + +#define RECEIVE_FIFO_TRIGGER1 0x0 /* trigger recieve interrupt after 1 byte */ +#define RECEIVE_FIFO_TRIGGER4 0x40 /* trigger recieve interrupt after 4 byte */ +#define RECEIVE_FIFO_TRIGGER8 0x80 /* trigger recieve interrupt after 8 byte */ +#define RECEIVE_FIFO_TRIGGER12 0xc0 /* trigger recieve interrupt after 12 byte */ +#define TRIG_LEVEL 0xc0 /* Mask for the trigger level */ + +#endif /* _BSPUART_H */ + + + diff --git a/c/src/lib/libbsp/i386/shared/irq/irq.c b/c/src/lib/libbsp/i386/shared/irq/irq.c index 9dea372e0f..cd38ec51c4 100644 --- a/c/src/lib/libbsp/i386/shared/irq/irq.c +++ b/c/src/lib/libbsp/i386/shared/irq/irq.c @@ -21,19 +21,19 @@ * pointer to the mask representing the additionnal irq vectors * that must be disabled when a particular entry is activated. * They will be dynamically computed from teh prioruty table given - * in pc386_rtems_irq_mngt_set(); + * in BSP_rtems_irq_mngt_set(); * CAUTION : this table is accessed directly by interrupt routine * prologue. */ -rtems_i8259_masks irq_mask_or_tbl[PC_386_IRQ_LINES_NUMBER]; +rtems_i8259_masks irq_mask_or_tbl[BSP_IRQ_LINES_NUMBER]; /* - * Copy of data given via initial pc386_rtems_irq_mngt_set() for + * Copy of data given via initial BSP_rtems_irq_mngt_set() for * the sake of efficiency. * CAUTION : this table is accessed directly by interrupt routine * prologue. */ -rtems_irq_hdl current_irq[PC_386_IRQ_LINES_NUMBER]; +rtems_irq_hdl current_irq[BSP_IRQ_LINES_NUMBER]; /* * default handler connected on each irq after bsp initialization */ @@ -56,19 +56,19 @@ static rtems_irq_connect_data* rtems_hdl_tbl; rtems_i8259_masks i8259s_cache; /*-------------------------------------------------------------------------+ -| Function: PC386_irq_disable_at_i8259s +| Function: BSP_irq_disable_at_i8259s | Description: Mask IRQ line in appropriate PIC chip. | Global Variables: i8259s_cache | Arguments: vector_offset - number of IRQ line to mask. | Returns: Nothing. +--------------------------------------------------------------------------*/ -int pc386_irq_disable_at_i8259s (const rtems_irq_symbolic_name irqLine) +int BSP_irq_disable_at_i8259s (const rtems_irq_symbolic_name irqLine) { unsigned short mask; unsigned int level; - if ( ((int)irqLine < PC_386_LOWEST_OFFSET) || - ((int)irqLine > PC_386_MAX_OFFSET ) + if ( ((int)irqLine < BSP_LOWEST_OFFSET) || + ((int)irqLine > BSP_MAX_OFFSET ) ) return 1; @@ -91,19 +91,19 @@ int pc386_irq_disable_at_i8259s (const rtems_irq_symbolic_name irqLine) } /*-------------------------------------------------------------------------+ -| Function: pc386_irq_enable_at_i8259s +| Function: BSP_irq_enable_at_i8259s | Description: Unmask IRQ line in appropriate PIC chip. | Global Variables: i8259s_cache | Arguments: irqLine - number of IRQ line to mask. | Returns: Nothing. +--------------------------------------------------------------------------*/ -int pc386_irq_enable_at_i8259s (const rtems_irq_symbolic_name irqLine) +int BSP_irq_enable_at_i8259s (const rtems_irq_symbolic_name irqLine) { unsigned short mask; unsigned int level; - if ( ((int)irqLine < PC_386_LOWEST_OFFSET) || - ((int)irqLine > PC_386_MAX_OFFSET ) + if ( ((int)irqLine < BSP_LOWEST_OFFSET) || + ((int)irqLine > BSP_MAX_OFFSET ) ) return 1; @@ -125,12 +125,12 @@ int pc386_irq_enable_at_i8259s (const rtems_irq_symbolic_name irqLine) return 0; } /* mask_irq */ -int pc386_irq_enabled_at_i8259s (const rtems_irq_symbolic_name irqLine) +int BSP_irq_enabled_at_i8259s (const rtems_irq_symbolic_name irqLine) { unsigned short mask; - if ( ((int)irqLine < PC_386_LOWEST_OFFSET) || - ((int)irqLine > PC_386_MAX_OFFSET ) + if ( ((int)irqLine < BSP_LOWEST_OFFSET) || + ((int)irqLine > BSP_MAX_OFFSET ) ) return 1; @@ -140,16 +140,16 @@ int pc386_irq_enabled_at_i8259s (const rtems_irq_symbolic_name irqLine) /*-------------------------------------------------------------------------+ -| Function: pc386_irq_ack_at_i8259s +| Function: BSP_irq_ack_at_i8259s | Description: Signal generic End Of Interrupt (EOI) to appropriate PIC. | Global Variables: None. | Arguments: irqLine - number of IRQ line to acknowledge. | Returns: Nothing. +--------------------------------------------------------------------------*/ -int pc386_irq_ack_at_i8259s (const rtems_irq_symbolic_name irqLine) +int BSP_irq_ack_at_i8259s (const rtems_irq_symbolic_name irqLine) { - if ( ((int)irqLine < PC_386_LOWEST_OFFSET) || - ((int)irqLine > PC_386_MAX_OFFSET ) + if ( ((int)irqLine < BSP_LOWEST_OFFSET) || + ((int)irqLine > BSP_MAX_OFFSET ) ) return 1; @@ -212,7 +212,7 @@ static void make_copy_of_handlers () static int isValidInterrupt(int irq) { - if ( (irq < PC_386_LOWEST_OFFSET) || (irq > PC_386_MAX_OFFSET)) + if ( (irq < BSP_LOWEST_OFFSET) || (irq > BSP_MAX_OFFSET)) return 0; return 1; } @@ -221,7 +221,7 @@ static int isValidInterrupt(int irq) * ------------------------ RTEMS Single Irq Handler Mngt Routines ---------------- */ -int pc386_install_rtems_irq_handler (const rtems_irq_connect_data* irq) +int BSP_install_rtems_irq_handler (const rtems_irq_connect_data* irq) { unsigned int level; @@ -251,7 +251,7 @@ int pc386_install_rtems_irq_handler (const rtems_irq_connect_data* irq) /* * Enable interrupt at PIC level */ - pc386_irq_enable_at_i8259s (irq->name); + BSP_irq_enable_at_i8259s (irq->name); /* * Enable interrupt on device */ @@ -263,7 +263,7 @@ int pc386_install_rtems_irq_handler (const rtems_irq_connect_data* irq) } -int pc386_get_current_rtems_irq_handler (rtems_irq_connect_data* irq) +int BSP_get_current_rtems_irq_handler (rtems_irq_connect_data* irq) { if (!isValidInterrupt(irq->name)) { return 0; @@ -272,7 +272,7 @@ int pc386_get_current_rtems_irq_handler (rtems_irq_connect_data* irq) return 1; } -int pc386_remove_rtems_irq_handler (const rtems_irq_connect_data* irq) +int BSP_remove_rtems_irq_handler (const rtems_irq_connect_data* irq) { unsigned int level; @@ -294,7 +294,7 @@ int pc386_remove_rtems_irq_handler (const rtems_irq_connect_data* irq) /* * disable interrupt at PIC level */ - pc386_irq_disable_at_i8259s (irq->name); + BSP_irq_disable_at_i8259s (irq->name); /* * Disable interrupt on device @@ -317,7 +317,7 @@ int pc386_remove_rtems_irq_handler (const rtems_irq_connect_data* irq) * ------------------------ RTEMS Global Irq Handler Mngt Routines ---------------- */ -int pc386_rtems_irq_mngt_set(rtems_irq_global_settings* config) +int BSP_rtems_irq_mngt_set(rtems_irq_global_settings* config) { int i; unsigned int level; @@ -337,23 +337,23 @@ int pc386_rtems_irq_mngt_set(rtems_irq_global_settings* config) for (i=0; i < internal_config->irqNb; i++) { if (rtems_hdl_tbl[i].hdl != default_rtems_entry.hdl) { - pc386_irq_enable_at_i8259s (i); + BSP_irq_enable_at_i8259s (i); rtems_hdl_tbl[i].on(&rtems_hdl_tbl[i]); } else { rtems_hdl_tbl[i].off(&rtems_hdl_tbl[i]); - pc386_irq_disable_at_i8259s (i); + BSP_irq_disable_at_i8259s (i); } } /* * must disable slave pic anyway */ - pc386_irq_enable_at_i8259s (2); + BSP_irq_enable_at_i8259s (2); _CPU_ISR_Enable(level); return 1; } -int pc386_rtems_irq_mngt_get(rtems_irq_global_settings** config) +int BSP_rtems_irq_mngt_get(rtems_irq_global_settings** config) { *config = internal_config; return 0; diff --git a/c/src/lib/libbsp/i386/shared/irq/irq.h b/c/src/lib/libbsp/i386/shared/irq/irq.h index 5d628af83b..8bb6ce6f85 100644 --- a/c/src/lib/libbsp/i386/shared/irq/irq.h +++ b/c/src/lib/libbsp/i386/shared/irq/irq.h @@ -37,27 +37,27 @@ extern "C" { typedef enum { /* Base vector for our IRQ handlers. */ - PC386_IRQ_VECTOR_BASE = PC386_ASM_IRQ_VECTOR_BASE, - PC_386_IRQ_LINES_NUMBER = 16, - PC_386_LOWEST_OFFSET = 0, - PC_386_MAX_OFFSET = PC_386_IRQ_LINES_NUMBER - 1, + BSP_IRQ_VECTOR_BASE = BSP_ASM_IRQ_VECTOR_BASE, + BSP_IRQ_LINES_NUMBER = 16, + BSP_LOWEST_OFFSET = 0, + BSP_MAX_OFFSET = BSP_IRQ_LINES_NUMBER - 1, /* - * Interrupt offset in comparison to PC386_ASM_IRQ_VECTOR_BASE - * NB : 1) Interrupt vector number in IDT = offset + PC386_ASM_IRQ_VECTOR_BASE + * Interrupt offset in comparison to BSP_ASM_IRQ_VECTOR_BASE + * NB : 1) Interrupt vector number in IDT = offset + BSP_ASM_IRQ_VECTOR_BASE * 2) The same name should be defined on all architecture * so that handler connexion can be unchanged. */ - PC_386_PERIODIC_TIMER = 0, + BSP_PERIODIC_TIMER = 0, - PC_386_KEYBOARD = 1, + BSP_KEYBOARD = 1, - PC386_UART_COM2_IRQ = 3, + BSP_UART_COM2_IRQ = 3, - PC386_UART_COM1_IRQ = 4, + BSP_UART_COM1_IRQ = 4, - PC_386_RT_TIMER1 = 8, + BSP_RT_TIMER1 = 8, - PC_386_RT_TIMER3 = 10 + BSP_RT_TIMER3 = 10 }rtems_irq_symbolic_name; @@ -127,7 +127,7 @@ typedef struct { */ rtems_irq_connect_data* irqHdlTbl; /* - * actual value of PC386_IRQ_VECTOR_BASE... + * actual value of BSP_IRQ_VECTOR_BASE... */ rtems_irq_symbolic_name irqBase; /* @@ -155,13 +155,13 @@ typedef struct { * this function, even if the device asserts the interrupt line it will * not be propagated further to the processor */ -int pc386_irq_disable_at_i8259s (const rtems_irq_symbolic_name irqLine); +int BSP_irq_disable_at_i8259s (const rtems_irq_symbolic_name irqLine); /* * function to enable a particular irq at 8259 level. After calling * this function, if the device asserts the interrupt line it will * be propagated further to the processor */ -int pc386_irq_enable_at_i8259s (const rtems_irq_symbolic_name irqLine); +int BSP_irq_enable_at_i8259s (const rtems_irq_symbolic_name irqLine); /* * function to acknoledge a particular irq at 8259 level. After calling * this function, if a device asserts an enabled interrupt line it will @@ -169,11 +169,11 @@ int pc386_irq_enable_at_i8259s (const rtems_irq_symbolic_name irqLine); * writting raw handlers as this is automagically done for rtems managed * handlers. */ -int pc386_irq_ack_at_i8259s (const rtems_irq_symbolic_name irqLine); +int BSP_irq_ack_at_i8259s (const rtems_irq_symbolic_name irqLine); /* * function to check if a particular irq is enabled at 8259 level. After calling */ -int pc386_irq_enabled_at_i8259s (const rtems_irq_symbolic_name irqLine); +int BSP_irq_enabled_at_i8259s (const rtems_irq_symbolic_name irqLine); /* * ------------------------ RTEMS Single Irq Handler Mngt Routines ---------------- */ @@ -211,18 +211,18 @@ int pc386_irq_enabled_at_i8259s (const rtems_irq_symbolic_name irqLine); * 6) restore initial execution flow * */ -int pc386_install_rtems_irq_handler (const rtems_irq_connect_data*); +int BSP_install_rtems_irq_handler (const rtems_irq_connect_data*); /* * function to get the current RTEMS irq handler for ptr->name. It enables to * define hanlder chain... */ -int pc386_get_current_rtems_irq_handler (rtems_irq_connect_data* ptr); +int BSP_get_current_rtems_irq_handler (rtems_irq_connect_data* ptr); /* * function to get disconnect the RTEMS irq handler for ptr->name. * This function checks that the value given is the current one for safety reason. * The user can use the previous function to get it. */ -int pc386_remove_rtems_irq_handler (const rtems_irq_connect_data*); +int BSP_remove_rtems_irq_handler (const rtems_irq_connect_data*); /* * ------------------------ RTEMS Global Irq Handler Mngt Routines ---------------- @@ -233,10 +233,10 @@ int pc386_remove_rtems_irq_handler (const rtems_irq_connect_data*); * The result of calling this function will be the same as if each individual * handler (config->irqHdlTbl[i].hdl) different from "config->defaultEntry.hdl" * has been individualy connected via - * pc386_install_rtems_irq_handler(&config->irqHdlTbl[i]) + * BSP_install_rtems_irq_handler(&config->irqHdlTbl[i]) * And each handler currently equal to config->defaultEntry.hdl * has been previously disconnected via - * pc386_remove_rtems_irq_handler (&config->irqHdlTbl[i]) + * BSP_remove_rtems_irq_handler (&config->irqHdlTbl[i]) * * This is to say that all information given will be used and not just * only the space. @@ -247,11 +247,11 @@ int pc386_remove_rtems_irq_handler (const rtems_irq_connect_data*); * not be modified or declared on a stack. */ -int pc386_rtems_irq_mngt_set(rtems_irq_global_settings* config); +int BSP_rtems_irq_mngt_set(rtems_irq_global_settings* config); /* * (Re) get info on current RTEMS interrupt management. */ -int pc386_rtems_irq_mngt_get(rtems_irq_global_settings**); +int BSP_rtems_irq_mngt_get(rtems_irq_global_settings**); #ifdef __cplusplus } diff --git a/c/src/lib/libbsp/i386/shared/irq/irq_asm.h b/c/src/lib/libbsp/i386/shared/irq/irq_asm.h index bf6bb17e8e..af1289fb8f 100644 --- a/c/src/lib/libbsp/i386/shared/irq/irq_asm.h +++ b/c/src/lib/libbsp/i386/shared/irq/irq_asm.h @@ -15,7 +15,7 @@ #ifndef __IRQ_ASM_H__ #define __IRQ_ASM_H__ -#define PC386_ASM_IRQ_VECTOR_BASE 0x20 +#define BSP_ASM_IRQ_VECTOR_BASE 0x20 /* PIC's command and mask registers */ #define PIC_MASTER_COMMAND_IO_PORT 0x20 /* Master PIC command register */ #define PIC_SLAVE_COMMAND_IO_PORT 0xa0 /* Slave PIC command register */ diff --git a/c/src/lib/libbsp/i386/shared/irq/irq_init.c b/c/src/lib/libbsp/i386/shared/irq/irq_init.c index ee6967d8d9..73cdf2e8c1 100644 --- a/c/src/lib/libbsp/i386/shared/irq/irq_init.c +++ b/c/src/lib/libbsp/i386/shared/irq/irq_init.c @@ -55,9 +55,9 @@ static rtems_raw_irq_connect_data idtHdl[IDT_SIZE]; /* * Table used to store rtems managed interrupt handlers. * Borrow the table to store raw handler entries at the beginning. - * The table will be reinitialized before the call to pc386_rtems_irq_mngt_set(). + * The table will be reinitialized before the call to BSP_rtems_irq_mngt_set(). */ -static rtems_irq_connect_data rtemsIrq[PC_386_IRQ_LINES_NUMBER] = { +static rtems_irq_connect_data rtemsIrq[BSP_IRQ_LINES_NUMBER] = { {0,(rtems_irq_hdl)rtems_irq_prologue_0}, {0,(rtems_irq_hdl)rtems_irq_prologue_1}, {0,(rtems_irq_hdl)rtems_irq_prologue_2}, @@ -86,7 +86,7 @@ static rtems_irq_connect_data defaultIrq = { 0, nop_func , nop_func , nop_func , not_connected }; -static rtems_irq_prio irqPrioTable[PC_386_IRQ_LINES_NUMBER]={ +static rtems_irq_prio irqPrioTable[BSP_IRQ_LINES_NUMBER]={ /* * actual rpiorities for interrupt : * 0 means that only current interrupt is masked @@ -155,9 +155,9 @@ void rtems_irq_mngt_init() * Patch the entry that will be used by RTEMS for interrupt management * with RTEMS prologue. */ - for (i = 0; i < PC_386_IRQ_LINES_NUMBER; i++) { + for (i = 0; i < BSP_IRQ_LINES_NUMBER; i++) { create_interrupt_gate_descriptor(&idtEntry,(rtems_raw_irq_hdl) rtemsIrq[i].hdl); - idt_entry_tbl[i + PC386_ASM_IRQ_VECTOR_BASE] = idtEntry; + idt_entry_tbl[i + BSP_ASM_IRQ_VECTOR_BASE] = idtEntry; } /* * At this point we have completed the initialization of IDT @@ -167,20 +167,20 @@ void rtems_irq_mngt_init() /* * re-init the rtemsIrq table */ - for (i = 0; i < PC_386_IRQ_LINES_NUMBER; i++) { + for (i = 0; i < BSP_IRQ_LINES_NUMBER; i++) { rtemsIrq[i] = defaultIrq; rtemsIrq[i].name = i; } /* * Init initial Interrupt management config */ - initial_config.irqNb = PC_386_IRQ_LINES_NUMBER; + initial_config.irqNb = BSP_IRQ_LINES_NUMBER; initial_config.defaultEntry = defaultIrq; initial_config.irqHdlTbl = rtemsIrq; - initial_config.irqBase = PC386_ASM_IRQ_VECTOR_BASE; + initial_config.irqBase = BSP_ASM_IRQ_VECTOR_BASE; initial_config.irqPrioTbl = irqPrioTable; - if (!pc386_rtems_irq_mngt_set(&initial_config)) { + if (!BSP_rtems_irq_mngt_set(&initial_config)) { /* * put something here that will show the failure... */ @@ -200,7 +200,7 @@ void rtems_irq_mngt_init() printk("idt_entry_tbl = %x Interrupt_descriptor_table addr = %x\n", idt_entry_tbl, &Interrupt_descriptor_table); - tmp = (unsigned) get_hdl_from_vector (PC386_ASM_IRQ_VECTOR_BASE + PC_386_PERIODIC_TIMER); + tmp = (unsigned) get_hdl_from_vector (BSP_ASM_IRQ_VECTOR_BASE + BSP_PERIODIC_TIMER); printk("clock isr address from idt = %x should be %x\n", tmp, (unsigned) rtems_irq_prologue_0); } diff --git a/c/src/lib/libbsp/i386/shared/pci/Makefile.in b/c/src/lib/libbsp/i386/shared/pci/Makefile.in new file mode 100644 index 0000000000..607f26030a --- /dev/null +++ b/c/src/lib/libbsp/i386/shared/pci/Makefile.in @@ -0,0 +1,32 @@ +# +# $Id$ +# + +@SET_MAKE@ +srcdir = @srcdir@ +VPATH = @srcdir@ +RTEMS_ROOT = @top_srcdir@ +PROJECT_ROOT = @PROJECT_ROOT@ + +H_FILES = $(srcdir)/pcibios.h + +# +# Equate files are for including from assembly preprocessed by +# gm4 or gasp. No examples are provided except for those for +# other CPUs. The best way to generate them would be to +# provide a program which generates the constants used based +# on the C equivalents. +# + +EQ_FILES = + +SRCS=$(H_FILES) $(EQ_FILES) + +include $(RTEMS_ROOT)/make/custom/$(RTEMS_BSP).cfg +include $(RTEMS_ROOT)/make/leaf.cfg + +CLEAN_ADDITIONS += +CLOBBER_ADDITIONS += + +preinstall all: $(SRCS) + $(INSTALL) -m 444 $(SRCS) $(PROJECT_INCLUDE) diff --git a/c/src/lib/libbsp/i386/shared/pci/pcibios.c b/c/src/lib/libbsp/i386/shared/pci/pcibios.c new file mode 100644 index 0000000000..483e5df2a9 --- /dev/null +++ b/c/src/lib/libbsp/i386/shared/pci/pcibios.c @@ -0,0 +1,499 @@ +/* + * This software is Copyright (C) 1998 by T.sqware - all rights limited + * It is provided in to the public domain "as is", can be freely modified + * as far as this copyight notice is kept unchanged, but does not imply + * an endorsement by T.sqware of the product in which it is included. + * + * $Id$ + */ + +#include <rtems.h> +#include <bsp.h> +#include <assert.h> +#include <pcibios.h> + +/* + * This is simpliest possible PCI BIOS, it assumes that addressing + * is flat and that stack is big enough + */ + + +static int pcibInitialized = 0; +static unsigned int pcibEntry; + +/* + * Array to pass data between c and asm parts, at the time of + * writing I am not yet that familiar with extended asm feature + * of gcc. This code is not on performance path, so we can care + * relatively little about performance here + */ +static volatile unsigned int pcibExchg[5]; + +static int pcib_convert_err(int err); + +/* + * Detects presense of PCI BIOS, returns + * error code + */ +int +pcib_init(void) +{ + unsigned char *ucp; + unsigned char sum; + int i; + + pcibInitialized = 0; + + /* First, we have to look for BIOS-32 */ + for(ucp=(unsigned char *)0xE0000; ucp < (unsigned char *)0xFFFFF; ucp+=0x10) + { + if(memcmp(ucp, "_32_", 4) != 0) + { + continue; + } + + /* Got signature, check length */ + if(*(ucp + 9) != 1) + { + continue; + } + + /* Verify checksum */ + sum = 0; + for(i=0; i<16; i++) + { + sum += *(ucp+i); + } + + if(sum == 0) + { + /* found */ + break; + } + } + + if(ucp >= (unsigned char *)0xFFFFF) + { + /* BIOS-32 not found */ + assert(0); + return PCIB_ERR_NOTPRESENT; + } + + /* BIOS-32 found, let us find PCI BIOS */ + ucp += 4; + + pcibExchg[0] = *(unsigned int *)ucp; + + asm (" pusha"); /* Push all registers */ + asm (" movl pcibExchg, %edi"); /* Move entry point to esi */ + asm (" movl $0x49435024, %eax"); /* Move signature to eax */ + asm (" xorl %ebx, %ebx"); /* Zero ebx */ + asm (" pushl %cs"); + asm (" call *%edi"); /* Call entry */ + asm (" movl %eax, pcibExchg"); + asm (" movl %ebx, pcibExchg+4"); + asm (" movl %ecx, pcibExchg+8"); + asm (" movl %edx, pcibExchg+12"); + asm (" popa"); + + if((pcibExchg[0] & 0xff) != 0) + { + /* Not found */ + assert(0); + return PCIB_ERR_NOTPRESENT; + } + + /* Found PCI entry point */ + pcibEntry = pcibExchg[1] + pcibExchg[3]; + + /* Let us check whether PCI bios is present */ + pcibExchg[0] = pcibEntry; + + asm(" pusha"); + asm(" movl pcibExchg, %edi"); + asm(" movb $0xb1, %ah"); + asm(" movb $0x01, %al"); + asm (" pushl %cs"); + asm(" call *%edi"); + asm(" movl %eax, pcibExchg"); + asm(" movl %ebx, pcibExchg+4"); + asm(" movl %ecx, pcibExchg+8"); + asm(" movl %edx, pcibExchg+12"); + asm(" popa"); + + if((pcibExchg[0] & 0xff00) != 0) + { + /* Not found */ + assert(0); + return PCIB_ERR_NOTPRESENT; + } + + if(pcibExchg[3] != 0x20494350) + { + /* Signature does not match */ + assert(0); + return PCIB_ERR_NOTPRESENT; + } + + /* Success */ + + pcibInitialized = 1; + return PCIB_ERR_SUCCESS; +} + +/* + * Find specified device and return its signature: combination + * of bus number, device number and function number + */ +int +pcib_find_by_devid(int vendorId, int devId, int idx, int *sig) +{ + if(!pcibInitialized) + { + assert(0); + return PCIB_ERR_UNINITIALIZED; + } + + pcibExchg[0] = pcibEntry; + pcibExchg[1] = vendorId; + pcibExchg[2] = devId; + pcibExchg[3] = idx; + + asm(" pusha"); + asm(" movl pcibExchg, %edi"); + asm(" movb $0xb1, %ah"); + asm(" movb $0x02, %al"); + asm(" movl pcibExchg+4, %edx"); + asm(" movl pcibExchg+8, %ecx"); + asm(" movl pcibExchg+12, %esi"); + asm(" pushl %cs"); + asm(" call *%edi"); + asm(" movl %eax, pcibExchg"); + asm(" movl %ebx, pcibExchg+4"); + asm(" popa"); + + *sig = pcibExchg[1] & 0xffff; + + return pcib_convert_err((pcibExchg[0] >> 8) & 0xff); +} + +/* + * Find specified class code return device signature: combination + * of bus number, device number and function number + */ +int +pcib_find_by_class(int classCode, int idx, int *sig) +{ + if(!pcibInitialized) + { + assert(0); + return PCIB_ERR_UNINITIALIZED; + } + + pcibExchg[0] = pcibEntry; + pcibExchg[1] = classCode; + pcibExchg[2] = idx; + + asm(" pusha"); + asm(" movl pcibExchg, %edi"); + asm(" movb $0xb1, %ah"); + asm(" movb $0x03, %al"); + asm(" movl pcibExchg+4, %ecx"); + asm(" movl pcibExchg+8, %esi"); + asm(" pushl %cs"); + asm(" call *%edi"); + asm(" movl %eax, pcibExchg"); + asm(" movl %ebx, pcibExchg+4"); + asm(" popa"); + + if((pcibExchg[0] & 0xff00) != 0) + { + return pcib_convert_err((pcibExchg[0] >> 8) & 0xff); + } + + *sig = pcibExchg[1] & 0xffff; + + return PCIB_ERR_SUCCESS; +} + + + +/* + * Generate Special Cycle + */ +int +pcib_special_cycle(int busNo, int data) +{ + if(!pcibInitialized) + { + assert(0); + return PCIB_ERR_UNINITIALIZED; + } + + pcibExchg[0] = pcibEntry; + pcibExchg[1] = busNo << 8; + pcibExchg[2] = data; + + asm(" pusha"); + asm(" movl pcibExchg, %edi"); + asm(" movb $0xb1, %ah"); + asm(" movb $0x06, %al"); + asm(" movl pcibExchg+4, %ebx"); + asm(" movl pcibExchg+8, %edx"); + asm(" pushl %cs"); + asm(" call *%edi"); + asm(" movl %eax, pcibExchg"); + asm(" movl %ebx, pcibExchg+4"); + asm(" popa"); + + return pcib_convert_err((pcibExchg[0] >> 8) & 0xff); +} + + +/* + * Read byte from config space + */ +int +pcib_conf_read8(int sig, int off, unsigned char *data) +{ + if(!pcibInitialized) + { + assert(0); + return PCIB_ERR_UNINITIALIZED; + } + + pcibExchg[0] = pcibEntry; + pcibExchg[1] = sig; + pcibExchg[2] = off; + + asm(" pusha"); + asm(" movl pcibExchg, %esi"); + asm(" movb $0xb1, %ah"); + asm(" movb $0x08, %al"); + asm(" movl pcibExchg+4, %ebx"); + asm(" movl pcibExchg+8, %edi"); + asm(" pushl %cs"); + asm(" call *%esi"); + asm(" movl %eax, pcibExchg"); + asm(" movl %ecx, pcibExchg+4"); + asm(" popa"); + + if((pcibExchg[0] & 0xff00) != 0) + { + return pcib_convert_err((pcibExchg[0] >> 8) & 0xff); + } + + *data = (unsigned char)pcibExchg[1] & 0xff; + + return PCIB_ERR_SUCCESS; +} + + +/* + * Read word from config space + */ +int +pcib_conf_read16(int sig, int off, unsigned short *data) +{ + if(!pcibInitialized) + { + assert(0); + return PCIB_ERR_UNINITIALIZED; + } + + pcibExchg[0] = pcibEntry; + pcibExchg[1] = sig; + pcibExchg[2] = off; + + asm(" pusha"); + asm(" movl pcibExchg, %esi"); + asm(" movb $0xb1, %ah"); + asm(" movb $0x09, %al"); + asm(" movl pcibExchg+4, %ebx"); + asm(" movl pcibExchg+8, %edi"); + asm(" pushl %cs"); + asm(" call *%esi"); + asm(" movl %eax, pcibExchg"); + asm(" movl %ecx, pcibExchg+4"); + asm(" popa"); + + if((pcibExchg[0] & 0xff00) != 0) + { + return pcib_convert_err((pcibExchg[0] >> 8) & 0xff); + } + + *data = (unsigned short)pcibExchg[1] & 0xffff; + + return PCIB_ERR_SUCCESS; +} + + +/* + * Read dword from config space + */ +int +pcib_conf_read32(int sig, int off, unsigned int *data) +{ + if(!pcibInitialized) + { + assert(0); + return PCIB_ERR_UNINITIALIZED; + } + + pcibExchg[0] = pcibEntry; + pcibExchg[1] = sig; + pcibExchg[2] = off; + + asm(" pusha"); + asm(" movl pcibExchg, %esi"); + asm(" movb $0xb1, %ah"); + asm(" movb $0x0a, %al"); + asm(" movl pcibExchg+4, %ebx"); + asm(" movl pcibExchg+8, %edi"); + asm(" pushl %cs"); + asm(" call *%esi"); + asm(" movl %eax, pcibExchg"); + asm(" movl %ecx, pcibExchg+4"); + asm(" popa"); + + if((pcibExchg[0] & 0xff00) != 0) + { + return pcib_convert_err((pcibExchg[0] >> 8) & 0xff); + } + + *data = (unsigned int)pcibExchg[1]; + + return PCIB_ERR_SUCCESS; +} + + +/* + * Write byte into config space + */ +int +pcib_conf_write8(int sig, int off, unsigned int data) +{ + if(!pcibInitialized) + { + assert(0); + return PCIB_ERR_UNINITIALIZED; + } + + pcibExchg[0] = pcibEntry; + pcibExchg[1] = sig; + pcibExchg[2] = off; + pcibExchg[3] = data & 0xff; + + asm(" pusha"); + asm(" movl pcibExchg, %esi"); + asm(" movb $0xb1, %ah"); + asm(" movb $0x0b, %al"); + asm(" movl pcibExchg+4, %ebx"); + asm(" movl pcibExchg+8, %edi"); + asm(" movl pcibExchg+12, %ecx"); + asm(" pushl %cs"); + asm(" call *%esi"); + asm(" movl %eax, pcibExchg"); + asm(" popa"); + + return pcib_convert_err((pcibExchg[0] >> 8) & 0xff); +} + +/* + * Write word into config space + */ +int +pcib_conf_write16(int sig, int off, unsigned int data) +{ + if(!pcibInitialized) + { + assert(0); + return PCIB_ERR_UNINITIALIZED; + } + + pcibExchg[0] = pcibEntry; + pcibExchg[1] = sig; + pcibExchg[2] = off; + pcibExchg[3] = data & 0xffff; + + asm(" pusha"); + asm(" movl pcibExchg, %esi"); + asm(" movb $0xb1, %ah"); + asm(" movb $0x0c, %al"); + asm(" movl pcibExchg+4, %ebx"); + asm(" movl pcibExchg+8, %edi"); + asm(" movl pcibExchg+12, %ecx"); + asm(" pushl %cs"); + asm(" call *%esi"); + asm(" movl %eax, pcibExchg"); + asm(" popa"); + + return pcib_convert_err((pcibExchg[0] >> 8) & 0xff); +} + + + +/* + * Write dword into config space + */ +int +pcib_conf_write32(int sig, int off, unsigned int data) +{ + if(!pcibInitialized) + { + assert(0); + return PCIB_ERR_UNINITIALIZED; + } + + pcibExchg[0] = pcibEntry; + pcibExchg[1] = sig; + pcibExchg[2] = off; + pcibExchg[3] = data; + + asm(" pusha"); + asm(" movl pcibExchg, %esi"); + asm(" movb $0xb1, %ah"); + asm(" movb $0x0d, %al"); + asm(" movl pcibExchg+4, %ebx"); + asm(" movl pcibExchg+8, %edi"); + asm(" movl pcibExchg+12, %ecx"); + asm(" pushl %cs"); + asm(" call *%esi"); + asm(" movl %eax, pcibExchg"); + asm(" popa"); + + return pcib_convert_err((pcibExchg[0] >> 8) & 0xff); +} + + +static int +pcib_convert_err(int err) +{ + switch(err & 0xff) + { + case 0: + return PCIB_ERR_SUCCESS; + case 0x81: + return PCIB_ERR_NOFUNC; + case 0x83: + return PCIB_ERR_BADVENDOR; + case 0x86: + return PCIB_ERR_DEVNOTFOUND; + case 0x87: + return PCIB_ERR_BADREG; + default: + assert(0); + break; + } + return PCIB_ERR_NOFUNC; +} + + + + + + + + + + diff --git a/c/src/lib/libbsp/i386/shared/pci/pcibios.h b/c/src/lib/libbsp/i386/shared/pci/pcibios.h new file mode 100644 index 0000000000..40bc3c861a --- /dev/null +++ b/c/src/lib/libbsp/i386/shared/pci/pcibios.h @@ -0,0 +1,46 @@ +/* + * This software is Copyright (C) 1998 by T.sqware - all rights limited + * It is provided in to the public domain "as is", can be freely modified + * as far as this copyight notice is kept unchanged, but does not imply + * an endorsement by T.sqware of the product in which it is included. + */ + +#ifndef _PCIB_H +#define _PCIB_H + +/* Error codes */ +#define PCIB_ERR_SUCCESS (0) +#define PCIB_ERR_UNINITIALIZED (-1) /* PCI BIOS is not initilized */ +#define PCIB_ERR_NOTPRESENT (-2) /* PCI BIOS not present */ +#define PCIB_ERR_NOFUNC (-3) /* Function not supported */ +#define PCIB_ERR_BADVENDOR (-4) /* Bad Vendor ID */ +#define PCIB_ERR_DEVNOTFOUND (-5) /* Device not found */ +#define PCIB_ERR_BADREG (-6) /* Bad register number */ + +/* + * Make device signature from bus number, device numebr and function + * number + */ +#define PCIB_DEVSIG_MAKE(b,d,f) ((b<<8)|(d<<3)|(f)) + +/* + * Extract valrous part from device signature + */ +#define PCIB_DEVSIG_BUS(x) (((x)>>8) &0xff) +#define PCIB_DEVSIG_DEV(x) (((x)>>3) & 0x1f) +#define PCIB_DEVSIG_FUNC(x) ((x) & 0x7) + +int pcib_init(void); +int pcib_find_by_devid(int vendorId, int devId, int idx, int *sig); +int pcib_find_by_class(int classCode, int idx, int *sig); +int pcib_special_cycle(int busNo, int data); +int pcib_conf_read8(int sig, int off, unsigned char *data); +int pcib_conf_read16(int sig, int off, unsigned short *data); +int pcib_conf_read32(int sig, int off, unsigned int *data); +int pcib_conf_write8(int sig, int off, unsigned int data); +int pcib_conf_write16(int sig, int off, unsigned int data); +int pcib_conf_write32(int sig, int off, unsigned int data); + + +#endif /* _PCIB_H */ + |