2003-02-20 Till Straumann <strauman@slac.stanford.edu>

PR 349/bsps
	* console/console.c, console/uart.c, console/uart.h: implement
	IOCTLs for the serial (UART) console to install/retrieve a BREAK-IRQ
	callback.  The callback routine (if installed) is invoked from the
	UART ISR when a BREAK interrupt is detected.  This can be used
	e.g. to enforce a "hotkey" reboot a la vxWorks Ctrl-X (although we
	use the serial line break condition) NOTE: The callback runs in
	ISR context.
This commit is contained in:
Joel Sherrill
2003-02-20 21:38:50 +00:00
parent 254f0552cb
commit 01fdbb1f30
6 changed files with 112 additions and 16 deletions

View File

@@ -1,3 +1,14 @@
2003-02-20 Till Straumann <strauman@slac.stanford.edu>
PR 349/bsps
* console/console.c, console/uart.c, console/uart.h: implement
IOCTLs for the serial (UART) console to install/retrieve a BREAK-IRQ
callback. The callback routine (if installed) is invoked from the
UART ISR when a BREAK interrupt is detected. This can be used
e.g. to enforce a "hotkey" reboot a la vxWorks Ctrl-X (although we
use the serial line break condition) NOTE: The callback runs in
ISR context.
2003-01-20 Joel Sherrill <joel@OARcorp.com>
* startup/linkcmds*: Add FreeBSD sysctl() sections.

View File

@@ -262,6 +262,19 @@ console_control(rtems_device_major_number major,
void *arg
)
{
/* does the BSP support break callbacks ? */
#if defined(BIOCSETBREAKCB) && defined(BIOCGETBREAKCB)
rtems_libio_ioctl_args_t *ioa=arg;
switch (ioa->command) {
case BIOCSETBREAKCB:
return BSP_uart_set_break_cb(minor, ioa);
case BIOCGETBREAKCB:
return BSP_uart_get_break_cb(minor, ioa);
default:
break;
}
#endif
return rtems_termios_ioctl (arg);
}

View File

@@ -888,7 +888,7 @@ static int skip_atoi(const char **s)
* bloat has been limited since we basically only need %u, %x, %s and %c.
* But we need 64 bit values !
*/
int vsprintf(char *buf, const char *fmt, va_list args);
int k_vsprintf(char *buf, const char *fmt, va_list args);
int printk(const char *fmt, ...) {
va_list args;
@@ -897,7 +897,7 @@ int printk(const char *fmt, ...) {
char buf[1024];
va_start(args, fmt);
i = vsprintf(buf, fmt, args);
i = k_vsprintf(buf, fmt, args);
va_end(args);
puts(buf);
return i;
@@ -988,7 +988,7 @@ static char * number(char * str, int size, int type, u64 num)
return str;
}
int vsprintf(char *buf, const char *fmt, va_list args)
int k_vsprintf(char *buf, const char *fmt, va_list args)
{
int len;
u64 num;

View File

@@ -1,6 +1,8 @@
/* $Id$ */
#include "console.inl"
#include <rtems/bspIo.h>
#include <libcpu/stackTrace.h>
/*-------------------------------------------------------------------------+
| Function: rtemsReboot
@@ -11,6 +13,8 @@
+--------------------------------------------------------------------------*/
void rtemsReboot(void)
{
printk("Printing a stack trace for your convenience :-)\n");
CPU_print_stack();
/* shutdown and reboot */
kbd_outb(0x4, 0xFE); /* use keyboard controler to do the job... */
} /* rtemsReboot */

View File

@@ -11,6 +11,7 @@
#include <bsp/irq.h>
#include <bsp/uart.h>
#include <rtems/libio.h>
#include <rtems/bspIo.h>
#include <assert.h>
/*
@@ -22,6 +23,7 @@ struct uart_data
unsigned long ioBase;
int hwFlow;
int baud;
BSP_UartBreakCbRec breakCallback;
};
/*
@@ -74,11 +76,13 @@ uwrite(int uart, int reg, unsigned int val)
out_8((unsigned char*)(uart_data[uart].ioBase + reg), val);
}
#define UARTDEBUG
#ifdef UARTDEBUG
static void
uartError(int uart)
uartError(int uart, void *termiosPrivate)
{
unsigned char uartStatus, dummy;
BSP_UartBreakCbProc h;
uartStatus = uread(uart, LSR);
dummy = uread(uart, RBR);
@@ -89,19 +93,32 @@ uartError(int uart)
printk("********* Parity Error **********\n");
if (uartStatus & FE)
printk("********* Framing Error **********\n");
if (uartStatus & BI)
printk("********* Parity Error **********\n");
if (uartStatus & BI) {
printk("********* BREAK INTERRUPT *********\n");
if ((h=uart_data[uart].breakCallback.handler))
h(uart,
(dummy<<8)|uartStatus,
termiosPrivate,
uart_data[uart].breakCallback.private);
}
if (uartStatus & ERFIFO)
printk("********* Error receive Fifo **********\n");
}
#else
inline void uartError(int uart)
inline void uartError(int uart, void *termiosPrivate)
{
unsigned char uartStatus;
unsigned char uartStatus,dummy;
BSP_UartBreakCbProc h;
uartStatus = uread(uart, LSR);
uartStatus = uread(uart, RBR);
dummy = uread(uart, RBR);
if ((uartStatus & BI) && (h=uart_data[uart].breakCallback.handler))
h(uart,
(dummy<<8)|uartStatus,
termiosPrivate,
uart_data[uart].breakCallback.private);
}
#endif
@@ -644,7 +661,7 @@ BSP_uart_termios_isr_com(int uart)
break;
case RECEIVER_ERROR:
/* RX error: eat character */
uartError(uart);
uartError(uart, termios_ttyp_com[uart]);
break;
default:
/* Should not happen */
@@ -666,3 +683,30 @@ BSP_uart_termios_isr_com2(void)
BSP_uart_termios_isr_com(BSP_UART_COM2);
}
/* retrieve 'break' handler info */
int
BSP_uart_get_break_cb(int uart, rtems_libio_ioctl_args_t *arg)
{
BSP_UartBreakCb cb=arg->buffer;
unsigned long flags;
SANITY_CHECK(uart);
rtems_interrupt_disable(flags);
*cb = uart_data[uart].breakCallback;
rtems_interrupt_enable(flags);
arg->ioctl_return=0;
return RTEMS_SUCCESSFUL;
}
/* install 'break' handler */
int
BSP_uart_set_break_cb(int uart, rtems_libio_ioctl_args_t *arg)
{
BSP_UartBreakCb cb=arg->buffer;
unsigned long flags;
SANITY_CHECK(uart);
rtems_interrupt_disable(flags);
uart_data[uart].breakCallback = *cb;
rtems_interrupt_enable(flags);
arg->ioctl_return=0;
return RTEMS_SUCCESSFUL;
}

View File

@@ -12,6 +12,9 @@
#include <bsp/irq.h>
#include <sys/ioctl.h>
#include <rtems/libio.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);
@@ -28,11 +31,32 @@ void BSP_uart_dbgisr_com1(void);
void BSP_uart_dbgisr_com2(void);
int BSP_uart_install_isr(int uart, rtems_irq_hdl handler);
int BSP_uart_remove_isr(int uart, rtems_irq_hdl handler);
int BSP_uart_get_break_cb(int uart, rtems_libio_ioctl_args_t *arg);
int BSP_uart_set_break_cb(int uart, rtems_libio_ioctl_args_t *arg);
extern unsigned BSP_poll_char_via_serial(void);
extern void BSP_output_char_via_serial(int val);
extern int BSPConsolePort;
extern int BSPBaseBaud;
/* Special IOCTLS to install a lowlevel 'BREAK' handler */
/* pass a BSP_UartBreakCb pointer to ioctl when retrieving
* or installing break callback
*/
typedef void (*BSP_UartBreakCbProc)(int uartMinor,
unsigned uartRBRLSRStatus,
void *termiosPrivatePtr,
void *private);
typedef struct BSP_UartBreakCbRec_ {
BSP_UartBreakCbProc handler; /* NOTE NOTE this handler runs in INTERRUPT CONTEXT */
void *private; /* closure pointer which is passed to the callback */
} BSP_UartBreakCbRec, *BSP_UartBreakCb;
#define BIOCGETBREAKCB _IOR('b',1,sizeof(BSP_UartBreakCbRec))
#define BIOCSETBREAKCB _IOW('b',2,sizeof(BSP_UartBreakCbRec))
/*
* Command values for BSP_uart_intr_ctrl(),
* values are strange in order to catch errors