summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--c/src/lib/libbsp/sparc/shared/include/cons.h12
-rw-r--r--c/src/lib/libbsp/sparc/shared/uart/apbuart_cons.c320
-rw-r--r--c/src/lib/libbsp/sparc/shared/uart/cons.c105
3 files changed, 232 insertions, 205 deletions
diff --git a/c/src/lib/libbsp/sparc/shared/include/cons.h b/c/src/lib/libbsp/sparc/shared/include/cons.h
index 4e095e5f05..9a26a26769 100644
--- a/c/src/lib/libbsp/sparc/shared/include/cons.h
+++ b/c/src/lib/libbsp/sparc/shared/include/cons.h
@@ -16,22 +16,20 @@
#ifndef __CONS_H__
#define __CONS_H__
+#include <rtems/termiostypes.h>
+
struct console_dev;
#define CONSOLE_FLAG_SYSCON 0x01
-struct console_cons_ops {
- void (*get_uart_attrs)(struct console_dev *, struct termios *t);
-};
-
struct console_dev {
- /* Set to non-zero if this UART should be system console and/or
+ rtems_termios_device_context base;
+ /* Set to CONSOLE_FLAG_SYSCON if this UART should be system console and/or
* debug console.
*/
int flags;
char *fsname; /* File system prefix */
- const struct rtems_termios_callbacks *callbacks; /* TERMIOS Callbacks */
- struct console_cons_ops ops;
+ const rtems_termios_device_handler *handler;
};
extern void console_dev_register(struct console_dev *dev);
diff --git a/c/src/lib/libbsp/sparc/shared/uart/apbuart_cons.c b/c/src/lib/libbsp/sparc/shared/uart/apbuart_cons.c
index c2beaeae02..27558e1848 100644
--- a/c/src/lib/libbsp/sparc/shared/uart/apbuart_cons.c
+++ b/c/src/lib/libbsp/sparc/shared/uart/apbuart_cons.c
@@ -18,7 +18,6 @@
/******************* Driver manager interface ***********************/
#include <bsp.h>
-#include <rtems/libio.h>
#include <stdlib.h>
#include <assert.h>
#include <rtems/bspIo.h>
@@ -55,23 +54,63 @@ struct apbuart_priv {
struct console_dev condev;
struct drvmgr_dev *dev;
struct apbuart_regs *regs;
+ struct rtems_termios_tty *tty;
char devName[32];
- void *cookie;
- int sending;
+ volatile int sending;
int mode;
};
+/* Getters for different interfaces. It happens to be just casting which we do
+ * in one place to avoid getting cast away. */
+static struct console_dev *base_get_condev(rtems_termios_device_context *base)
+{
+ return (struct console_dev *) base;
+}
+
+static struct apbuart_priv *condev_get_priv(struct console_dev *condev)
+{
+ return (struct apbuart_priv *) condev;
+}
+
+static struct apbuart_priv *base_get_priv(rtems_termios_device_context *base)
+{
+ return condev_get_priv(base_get_condev(base));
+}
+
/* TERMIOS Layer Callback functions */
-void apbuart_get_attributes(struct console_dev *condev, struct termios *t);
-int apbuart_set_attributes(int minor, const struct termios *t);
-ssize_t apbuart_write_polled(int minor, const char *buf, size_t len);
-int apbuart_pollRead(int minor);
-ssize_t apbuart_write_intr(int minor, const char *buf, size_t len);
-int apbuart_pollRead_task(int minor);
-int apbuart_firstOpen(int major, int minor, void *arg);
-int apbuart_lastClose(int major, int minor, void *arg);
-
-void apbuart_isr(void *arg);
+static bool first_open(
+ rtems_termios_tty *tty,
+ rtems_termios_device_context *base,
+ struct termios *term,
+ rtems_libio_open_close_args_t *args
+);
+static void last_close(
+ rtems_termios_tty *tty,
+ rtems_termios_device_context *base,
+ rtems_libio_open_close_args_t *args
+);
+static void write_interrupt(
+ rtems_termios_device_context *base,
+ const char *buf,
+ size_t len
+);
+static bool set_attributes(
+ rtems_termios_device_context *base,
+ const struct termios *t
+);
+static void get_attributes(
+ rtems_termios_device_context *base,
+ struct termios *t
+);
+static int read_polled(rtems_termios_device_context *base);
+static int read_task(rtems_termios_device_context *base);
+static void write_polled(
+ rtems_termios_device_context *base,
+ const char *buf,
+ size_t len
+);
+
+static void apbuart_cons_isr(void *arg);
int apbuart_get_baud(struct apbuart_priv *uart);
int apbuart_init1(struct drvmgr_dev *dev);
@@ -121,40 +160,30 @@ void apbuart_cons_register_drv (void)
drvmgr_drv_register(&apbuart_drv_info.general);
}
-/* Interrupt mode routines */
-static const rtems_termios_callbacks Callbacks_intr = {
- apbuart_firstOpen, /* firstOpen */
- apbuart_lastClose, /* lastClose */
- NULL, /* pollRead */
- apbuart_write_intr, /* write */
- apbuart_set_attributes, /* setAttributes */
- NULL, /* stopRemoteTx */
- NULL, /* startRemoteTx */
- TERMIOS_IRQ_DRIVEN /* outputUsesInterrupts */
+static const rtems_termios_device_handler handler_interrupt = {
+ .first_open = first_open,
+ .last_close = last_close,
+ .write = write_interrupt,
+ .set_attributes = set_attributes,
+ .mode = TERMIOS_IRQ_DRIVEN
};
-/* Polling mode routines */
-static const rtems_termios_callbacks Callbacks_task = {
- apbuart_firstOpen, /* firstOpen */
- apbuart_lastClose, /* lastClose */
- apbuart_pollRead_task, /* pollRead */
- apbuart_write_intr, /* write */
- apbuart_set_attributes, /* setAttributes */
- NULL, /* stopRemoteTx */
- NULL, /* startRemoteTx */
- TERMIOS_TASK_DRIVEN /* outputUsesInterrupts */
+static const rtems_termios_device_handler handler_task = {
+ .first_open = first_open,
+ .last_close = last_close,
+ .poll_read = read_task,
+ .write = write_interrupt,
+ .set_attributes = set_attributes,
+ .mode = TERMIOS_TASK_DRIVEN
};
-/* Polling mode routines */
-static const rtems_termios_callbacks Callbacks_poll = {
- apbuart_firstOpen, /* firstOpen */
- apbuart_lastClose, /* lastClose */
- apbuart_pollRead, /* pollRead */
- apbuart_write_polled, /* write */
- apbuart_set_attributes, /* setAttributes */
- NULL, /* stopRemoteTx */
- NULL, /* startRemoteTx */
- TERMIOS_POLLED /* outputUsesInterrupts */
+static const rtems_termios_device_handler handler_polled = {
+ .first_open = first_open,
+ .last_close = last_close,
+ .poll_read = read_polled,
+ .write = write_polled,
+ .set_attributes = set_attributes,
+ .mode = TERMIOS_POLLED
};
int apbuart_init1(struct drvmgr_dev *dev)
@@ -247,7 +276,6 @@ int apbuart_init1(struct drvmgr_dev *dev)
}
priv->condev.fsname = NULL;
- priv->condev.ops.get_uart_attrs = apbuart_get_attributes;
/* Select 0=Polled, 1=IRQ, 2=Task-Driven UART Mode */
value = drvmgr_dev_key_get(priv->dev, "mode", DRVMGR_KT_INT);
@@ -255,12 +283,13 @@ int apbuart_init1(struct drvmgr_dev *dev)
priv->mode = value->i;
else
priv->mode = TERMIOS_POLLED;
+ /* TERMIOS device handlers */
if (priv->mode == TERMIOS_IRQ_DRIVEN) {
- priv->condev.callbacks = &Callbacks_intr;
+ priv->condev.handler = &handler_interrupt;
} else if (priv->mode == TERMIOS_TASK_DRIVEN) {
- priv->condev.callbacks = &Callbacks_task;
+ priv->condev.handler = &handler_task;
} else {
- priv->condev.callbacks = &Callbacks_poll;
+ priv->condev.handler = &handler_polled;
}
/* Get Filesystem name prefix */
@@ -367,39 +396,58 @@ int apbuart_inbyte_nonblocking(struct apbuart_regs *regs)
}
#endif
-int apbuart_firstOpen(int major, int minor, void *arg)
+static bool first_open(
+ rtems_termios_tty *tty,
+ rtems_termios_device_context *base,
+ struct termios *term,
+ rtems_libio_open_close_args_t *args
+)
{
- struct apbuart_priv *uart = (struct apbuart_priv *)minor;
- rtems_libio_open_close_args_t *ioarg = arg;
+ struct apbuart_priv *uart = base_get_priv(base);
- if ( ioarg && ioarg->iop )
- uart->cookie = ioarg->iop->data1;
- else
- uart->cookie = NULL;
+ uart->tty = tty;
+
+ /* Preserve values set by bootloader */
+ get_attributes(base, term);
+ term->c_oflag |= ONLCR;
+ set_attributes(base, term);
/* Enable TX/RX */
- uart->regs->ctrl |= LEON_REG_UART_CTRL_RE | LEON_REG_UART_CTRL_TE;
+ uart->regs->ctrl |= APBUART_CTRL_RE | APBUART_CTRL_TE;
if (uart->mode != TERMIOS_POLLED) {
+ int ret;
+
/* Register interrupt and enable it */
- drvmgr_interrupt_register(uart->dev, 0, "apbuart",
- apbuart_isr, uart);
+ ret = drvmgr_interrupt_register(
+ uart->dev, 0, "apbuart", apbuart_cons_isr, tty
+ );
+ if (ret) {
+ return false;
+ }
uart->sending = 0;
/* Turn on RX interrupts */
- uart->regs->ctrl |= LEON_REG_UART_CTRL_RI;
+ uart->regs->ctrl |= APBUART_CTRL_RI;
}
- return 0;
+ return true;
}
-int apbuart_lastClose(int major, int minor, void *arg)
+static void last_close(
+ rtems_termios_tty *tty,
+ rtems_termios_device_context *base,
+ rtems_libio_open_close_args_t *args
+)
{
- struct apbuart_priv *uart = (struct apbuart_priv *)minor;
+ struct apbuart_priv *uart = base_get_priv(base);
+ rtems_interrupt_lock_context lock_context;
if (uart->mode != TERMIOS_POLLED) {
/* Turn off RX interrupts */
- uart->regs->ctrl &= ~(LEON_REG_UART_CTRL_RI);
+ rtems_termios_device_lock_acquire(base, &lock_context);
+ uart->regs->ctrl &= ~(APBUART_CTRL_RI);
+ rtems_termios_device_lock_release(base, &lock_context);
/**** Flush device ****/
while (uart->sending) {
@@ -407,42 +455,42 @@ int apbuart_lastClose(int major, int minor, void *arg)
}
/* Disable and unregister interrupt handler */
- drvmgr_interrupt_unregister(uart->dev, 0, apbuart_isr, uart);
+ drvmgr_interrupt_unregister(uart->dev, 0, apbuart_cons_isr, tty);
}
#ifdef LEON3
/* Disable TX/RX if not used for DEBUG */
if (uart->regs != dbg_uart)
- uart->regs->ctrl &= ~(LEON_REG_UART_CTRL_RE | LEON_REG_UART_CTRL_TE);
+ uart->regs->ctrl &= ~(APBUART_CTRL_RE | APBUART_CTRL_TE);
#endif
-
- return 0;
}
-int apbuart_pollRead(int minor)
+static int read_polled(rtems_termios_device_context *base)
{
- struct apbuart_priv *uart = (struct apbuart_priv *)minor;
+ struct apbuart_priv *uart = base_get_priv(base);
return apbuart_inbyte_nonblocking(uart->regs);
}
-int apbuart_pollRead_task(int minor)
+static int read_task(rtems_termios_device_context *base)
{
- struct apbuart_priv *uart = (struct apbuart_priv *)minor;
+ struct apbuart_priv *uart = base_get_priv(base);
int c, tot;
char buf[32];
+ struct rtems_termios_tty *tty;
+ tty = uart->tty;
tot = 0;
while ((c=apbuart_inbyte_nonblocking(uart->regs)) != EOF) {
buf[tot] = c;
tot++;
if (tot > 31) {
- rtems_termios_enqueue_raw_characters(uart->cookie, buf, tot);
+ rtems_termios_enqueue_raw_characters(tty, buf, tot);
tot = 0;
}
}
if (tot > 0)
- rtems_termios_enqueue_raw_characters(uart->cookie, buf, tot);
+ rtems_termios_enqueue_raw_characters(tty, buf, tot);
return EOF;
}
@@ -517,13 +565,17 @@ static struct apbuart_baud *apbuart_get_baud_closest(struct apbuart_priv *uart)
return apbuart_baud_find_closest(apbuart_get_baud(uart));
}
-int apbuart_set_attributes(int minor, const struct termios *t)
+static bool set_attributes(
+ rtems_termios_device_context *base,
+ const struct termios *t
+)
{
unsigned int core_clk_hz;
unsigned int scaler;
unsigned int ctrl;
int baud;
- struct apbuart_priv *uart = (struct apbuart_priv *)minor;
+ struct apbuart_priv *uart = base_get_priv(base);
+ rtems_interrupt_lock_context lock_context;
switch(t->c_cflag & CSIZE) {
default:
@@ -531,11 +583,13 @@ int apbuart_set_attributes(int minor, const struct termios *t)
case CS6:
case CS7:
/* Hardware doesn't support other than CS8 */
- return -1;
+ return false;
case CS8:
break;
}
+ rtems_termios_device_lock_acquire(base, &lock_context);
+
/* Read out current value */
ctrl = uart->regs->ctrl;
@@ -566,6 +620,8 @@ int apbuart_set_attributes(int minor, const struct termios *t)
/* Update new settings */
uart->regs->ctrl = ctrl;
+ rtems_termios_device_lock_release(base, &lock_context);
+
/* Baud rate */
baud = apbuart_baud_num2baud(t->c_ospeed);
if (baud > 0){
@@ -579,12 +635,15 @@ int apbuart_set_attributes(int minor, const struct termios *t)
uart->regs->scaler = scaler;
}
- return 0;
+ return true;
}
-void apbuart_get_attributes(struct console_dev *condev, struct termios *t)
+static void get_attributes(
+ rtems_termios_device_context *base,
+ struct termios *t
+)
{
- struct apbuart_priv *uart = (struct apbuart_priv *)condev;
+ struct apbuart_priv *uart = base_get_priv(base);
unsigned int ctrl;
struct apbuart_baud *baud;
@@ -609,82 +668,109 @@ void apbuart_get_attributes(struct console_dev *condev, struct termios *t)
t->c_cflag |= baud->num;
}
-ssize_t apbuart_write_polled(int minor, const char *buf, size_t len)
+static void write_polled(
+ rtems_termios_device_context *base,
+ const char *buf,
+ size_t len
+)
{
+ struct apbuart_priv *uart = base_get_priv(base);
int nwrite = 0;
- struct apbuart_priv *uart = (struct apbuart_priv *)minor;
while (nwrite < len) {
apbuart_outbyte_polled(uart->regs, *buf++, 0, 0);
nwrite++;
}
- return nwrite;
}
-ssize_t apbuart_write_intr(int minor, const char *buf, size_t len)
+static void write_interrupt(
+ rtems_termios_device_context *base,
+ const char *buf,
+ size_t len
+)
{
- struct apbuart_priv *uart = (struct apbuart_priv *)minor;
- unsigned int oldLevel;
+ struct apbuart_priv *uart = base_get_priv(base);
+ struct apbuart_regs *regs = uart->regs;
+ int sending;
unsigned int ctrl;
- rtems_interrupt_disable(oldLevel);
+ ctrl = regs->ctrl;
- /* Enable TX interrupt */
- ctrl = uart->regs->ctrl;
- uart->regs->ctrl = ctrl | LEON_REG_UART_CTRL_TI;
-
- if (ctrl & LEON_REG_UART_CTRL_FA) {
- /* APBUART with FIFO.. Fill as many as FIFO allows */
- uart->sending = 0;
- while (((uart->regs->status & LEON_REG_UART_STATUS_TF) == 0) &&
- (uart->sending < len)) {
- uart->regs->data = *buf;
- buf++;
- uart->sending++;
+ if (len > 0) {
+ /*
+ * sending is used to remember how much we have outstanding so
+ * we can tell termios later.
+ */
+ /* Enable TX interrupt (interrupt is edge-triggered) */
+ regs->ctrl = ctrl | APBUART_CTRL_TI;
+
+ if (ctrl & APBUART_CTRL_FA) {
+ /* APBUART with FIFO.. Fill as many as FIFO allows */
+ sending = 0;
+ while (
+ ((regs->status & APBUART_STATUS_TF) == 0) &&
+ (sending < len)
+ ) {
+ regs->data = *buf;
+ buf++;
+ sending++;
+ }
+ } else {
+ /* start UART TX, this will result in an interrupt when done */
+ regs->data = *buf;
+
+ sending = 1;
}
} else {
- /* start UART TX, this will result in an interrupt when done */
- uart->regs->data = *buf;
+ /* No more to send, disable TX interrupts */
+ regs->ctrl = ctrl & ~APBUART_CTRL_TI;
- uart->sending = 1;
+ /* Tell close that we sent everything */
+ sending = 0;
}
- rtems_interrupt_enable(oldLevel);
-
- return 0;
+ uart->sending = sending;
}
/* Handle UART interrupts */
-void apbuart_isr(void *arg)
+static void apbuart_cons_isr(void *arg)
{
- struct apbuart_priv *uart = arg;
+ rtems_termios_tty *tty = arg;
+ struct console_dev *condev = rtems_termios_get_device_context(tty);
+ struct apbuart_priv *uart = condev_get_priv(condev);
+ struct apbuart_regs *regs = uart->regs;
unsigned int status;
char data;
int cnt;
- /* Get all received characters */
if (uart->mode == TERMIOS_TASK_DRIVEN) {
- if ((status=uart->regs->status) & LEON_REG_UART_STATUS_DR)
- rtems_termios_rxirq_occured(uart->cookie);
+ if ((status=regs->status) & APBUART_STATUS_DR) {
+ /* Activate termios RX daemon task */
+ rtems_termios_rxirq_occured(tty);
+ }
} else {
- while ((status=uart->regs->status) & LEON_REG_UART_STATUS_DR) {
+ /* Get all received characters */
+ while ((status=regs->status) & APBUART_STATUS_DR) {
/* Data has arrived, get new data */
- data = uart->regs->data;
+ data = regs->data;
/* Tell termios layer about new character */
- rtems_termios_enqueue_raw_characters(uart->cookie, &data, 1);
+ rtems_termios_enqueue_raw_characters(tty, &data, 1);
}
}
- if (uart->sending && (status & LEON_REG_UART_STATUS_THE)) {
- /* Sent the one char, we disable TX interrupts */
- uart->regs->ctrl &= ~LEON_REG_UART_CTRL_TI;
-
+ if (uart->sending && (status & APBUART_STATUS_TE)) {
/* Tell close that we sent everything */
cnt = uart->sending;
uart->sending = 0;
- /* apbuart_write_intr() will get called from this function */
- rtems_termios_dequeue_characters(uart->cookie, cnt);
+ /*
+ * Tell termios how much we have sent. dequeue() may call
+ * write_interrupt() to refill the transmitter.
+ * write_interrupt() will eventually be called with 0 len to
+ * disable TX interrupts.
+ */
+ rtems_termios_dequeue_characters(tty, cnt);
}
}
+
diff --git a/c/src/lib/libbsp/sparc/shared/uart/cons.c b/c/src/lib/libbsp/sparc/shared/uart/cons.c
index 7d113b2ff7..8426adddf4 100644
--- a/c/src/lib/libbsp/sparc/shared/uart/cons.c
+++ b/c/src/lib/libbsp/sparc/shared/uart/cons.c
@@ -14,9 +14,8 @@
#include <bsp.h>
#include <stdlib.h>
-#include <rtems/libio.h>
-#include <rtems/bspIo.h>
#include <bsp/cons.h>
+#include <rtems/console.h>
#ifdef RTEMS_DRVMGR_STARTUP
@@ -26,25 +25,26 @@
* handle interrupts.
*/
-int console_initialized = 0;
-rtems_device_major_number console_major = 0;
+static int console_initialized = 0;
#define FLAG_SYSCON 0x01
struct console_priv {
- unsigned char flags; /* 0x1=SystemConsole */
- unsigned char minor;
+ int flags; /* 0x1=SystemConsole */
+ int minor;
struct console_dev *dev;
};
#define CONSOLE_MAX BSP_NUMBER_OF_TERMIOS_PORTS
struct console_priv cons[CONSOLE_MAX] = {{0,0},};
-/* Register Console to TERMIOS layer and initialize it */
-static void console_dev_init(struct console_priv *con, int minor)
+/* Install Console in TERMIOS layer */
+static void console_dev_init(struct console_priv *con)
{
char name[16], *fsname;
rtems_status_code status;
+ int minor;
+ minor = con->minor;
if (!con->dev->fsname) {
strcpy(name, "/dev/console_a");
/* Special console name and MINOR for SYSTEM CONSOLE */
@@ -55,11 +55,18 @@ static void console_dev_init(struct console_priv *con, int minor)
} else {
fsname = con->dev->fsname;
}
- status = rtems_io_register_name(fsname, console_major, minor);
- if ((minor == 0) && (status != RTEMS_SUCCESSFUL))
+ status = rtems_termios_device_install(
+ fsname,
+ con->dev->handler,
+ NULL,
+ &con->dev->base
+ );
+ if (status != RTEMS_SUCCESSFUL) {
rtems_fatal_error_occurred(status);
+ }
}
+/* Called by device driver to register itself to the cons interface. */
void console_dev_register(struct console_dev *dev)
{
int i, minor = 0;
@@ -87,11 +94,12 @@ void console_dev_register(struct console_dev *dev)
con->dev = dev;
con->minor = minor;
- /* Console layer is already initialized, that means that we can
- * register termios interface directly.
- */
- if (console_initialized)
- console_dev_init(con, minor);
+ if (console_initialized) {
+ /* Console layer is already initialized, that means that we can
+ * register termios interface directly.
+ */
+ console_dev_init(con);
+ }
}
#if 0
@@ -108,14 +116,12 @@ rtems_device_driver console_initialize(
{
int i;
- console_major = major;
-
rtems_termios_initialize();
/* Register all Console a file system device node */
for (i=0; i<CONSOLE_MAX; i++) {
if (cons[i].dev)
- console_dev_init(&cons[i], i);
+ console_dev_init(&cons[i]);
}
console_initialized = 1;
@@ -123,67 +129,4 @@ rtems_device_driver console_initialize(
return RTEMS_SUCCESSFUL;
}
-rtems_device_driver console_open(
- rtems_device_major_number major,
- rtems_device_minor_number minor,
- void *arg)
-{
- rtems_status_code status;
- struct termios term;
-
- if ((minor >= CONSOLE_MAX) || !cons[minor].dev)
- return RTEMS_INVALID_NUMBER;
-
- status = rtems_termios_open(
- major,
- (int)cons[minor].dev,
- arg,
- cons[minor].dev->callbacks);
-
- /* Inherit UART hardware parameters from bootloader on system console */
- if ((status == RTEMS_SUCCESSFUL) && (cons[minor].flags & FLAG_SYSCON) &&
- (cons[minor].dev->ops.get_uart_attrs != NULL)) {
- if (tcgetattr(STDIN_FILENO, &term) >= 0) {
- cons[minor].dev->ops.get_uart_attrs(cons[minor].dev,
- &term);
- term.c_oflag |= ONLCR;
- tcsetattr(STDIN_FILENO, TCSANOW, &term);
- }
- }
-
- return status;
-}
-
-rtems_device_driver console_close(
- rtems_device_major_number major,
- rtems_device_minor_number minor,
- void *arg)
-{
- return rtems_termios_close(arg);
-}
-
-rtems_device_driver console_read(
- rtems_device_major_number major,
- rtems_device_minor_number minor,
- void *arg)
-{
- return rtems_termios_read(arg);
-}
-
-rtems_device_driver console_write(
- rtems_device_major_number major,
- rtems_device_minor_number minor,
- void *arg)
-{
- return rtems_termios_write(arg);
-}
-
-rtems_device_driver console_control(
- rtems_device_major_number major,
- rtems_device_minor_number minor,
- void *arg)
-{
- return rtems_termios_ioctl(arg);
-}
-
#endif