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> 2003-01-20 Joel Sherrill <joel@OARcorp.com>
* startup/linkcmds*: Add FreeBSD sysctl() sections. * startup/linkcmds*: Add FreeBSD sysctl() sections.

View File

@@ -257,11 +257,24 @@ console_write(rtems_device_major_number major,
* Handle ioctl request. * Handle ioctl request.
*/ */
rtems_device_driver rtems_device_driver
console_control(rtems_device_major_number major, console_control(rtems_device_major_number major,
rtems_device_minor_number minor, rtems_device_minor_number minor,
void * arg 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); 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. * bloat has been limited since we basically only need %u, %x, %s and %c.
* But we need 64 bit values ! * 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, ...) { int printk(const char *fmt, ...) {
va_list args; va_list args;
@@ -897,7 +897,7 @@ int printk(const char *fmt, ...) {
char buf[1024]; char buf[1024];
va_start(args, fmt); va_start(args, fmt);
i = vsprintf(buf, fmt, args); i = k_vsprintf(buf, fmt, args);
va_end(args); va_end(args);
puts(buf); puts(buf);
return i; return i;
@@ -988,7 +988,7 @@ static char * number(char * str, int size, int type, u64 num)
return str; 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; int len;
u64 num; u64 num;

View File

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

View File

@@ -11,6 +11,7 @@
#include <bsp/irq.h> #include <bsp/irq.h>
#include <bsp/uart.h> #include <bsp/uart.h>
#include <rtems/libio.h> #include <rtems/libio.h>
#include <rtems/bspIo.h>
#include <assert.h> #include <assert.h>
/* /*
@@ -19,9 +20,10 @@
struct uart_data struct uart_data
{ {
unsigned long ioBase; unsigned long ioBase;
int hwFlow; int hwFlow;
int baud; 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); out_8((unsigned char*)(uart_data[uart].ioBase + reg), val);
} }
#define UARTDEBUG
#ifdef UARTDEBUG #ifdef UARTDEBUG
static void static void
uartError(int uart) uartError(int uart, void *termiosPrivate)
{ {
unsigned char uartStatus, dummy; unsigned char uartStatus, dummy;
BSP_UartBreakCbProc h;
uartStatus = uread(uart, LSR); uartStatus = uread(uart, LSR);
dummy = uread(uart, RBR); dummy = uread(uart, RBR);
@@ -89,19 +93,32 @@ uartError(int uart)
printk("********* Parity Error **********\n"); printk("********* Parity Error **********\n");
if (uartStatus & FE) if (uartStatus & FE)
printk("********* Framing Error **********\n"); printk("********* Framing Error **********\n");
if (uartStatus & BI) if (uartStatus & BI) {
printk("********* Parity Error **********\n"); 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) if (uartStatus & ERFIFO)
printk("********* Error receive Fifo **********\n"); printk("********* Error receive Fifo **********\n");
} }
#else #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, 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 #endif
@@ -644,7 +661,7 @@ BSP_uart_termios_isr_com(int uart)
break; break;
case RECEIVER_ERROR: case RECEIVER_ERROR:
/* RX error: eat character */ /* RX error: eat character */
uartError(uart); uartError(uart, termios_ttyp_com[uart]);
break; break;
default: default:
/* Should not happen */ /* Should not happen */
@@ -666,3 +683,30 @@ BSP_uart_termios_isr_com2(void)
BSP_uart_termios_isr_com(BSP_UART_COM2); 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 <bsp/irq.h>
#include <sys/ioctl.h>
#include <rtems/libio.h>
void BSP_uart_init(int uart, int baud, int hwFlow); void BSP_uart_init(int uart, int baud, int hwFlow);
void BSP_uart_set_baud(int aurt, int baud); void BSP_uart_set_baud(int aurt, int baud);
void BSP_uart_intr_ctrl(int uart, int cmd); 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); void BSP_uart_dbgisr_com2(void);
int BSP_uart_install_isr(int uart, rtems_irq_hdl handler); 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_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 unsigned BSP_poll_char_via_serial(void);
extern void BSP_output_char_via_serial(int val); extern void BSP_output_char_via_serial(int val);
extern int BSPConsolePort; extern int BSPConsolePort;
extern int BSPBaseBaud; 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(), * Command values for BSP_uart_intr_ctrl(),
* values are strange in order to catch errors * values are strange in order to catch errors