Discussion:
[PATCH 1/7] termios: Separate flow control from normal handler
Sebastian Huber
2014-10-07 14:36:25 UTC
Permalink
---
c/src/lib/libbsp/arm/tms570/console/tms570-sci.c | 5 +--
c/src/lib/libbsp/sparc/leon3/console/console.c | 2 +
cpukit/libcsupport/include/rtems/termiostypes.h | 35 ++++++++++++-----
cpukit/libcsupport/src/termios.c | 23 +++++++----
doc/bsp_howto/console.t | 1 +
testsuites/libtests/termios01/init.c | 49 ++++++++++++++++++++----
6 files changed, 87 insertions(+), 28 deletions(-)

diff --git a/c/src/lib/libbsp/arm/tms570/console/tms570-sci.c b/c/src/lib/libbsp/arm/tms570/console/tms570-sci.c
index 8aa3caf..961754e 100644
--- a/c/src/lib/libbsp/arm/tms570/console/tms570-sci.c
+++ b/c/src/lib/libbsp/arm/tms570/console/tms570-sci.c
@@ -103,6 +103,7 @@ rtems_device_driver console_initialize(
major,
minor,
handler,
+ NULL,
(void *) ctx
);
if ( sc != RTEMS_SUCCESSFUL ) {
@@ -536,8 +537,6 @@ const rtems_termios_device_handler tms570_sci_handler_polled = {
.poll_read = tms570_sci_poll_read,
.write = tms570_sci_poll_write,
.set_attributes = tms570_sci_set_attributes,
- .stop_remote_tx = NULL,
- .start_remote_tx = NULL,
.mode = TERMIOS_POLLED
};

@@ -553,7 +552,5 @@ const rtems_termios_device_handler tms570_sci_handler_interrupt = {
.poll_read = NULL,
.write = tms570_sci_interrupt_write,
.set_attributes = tms570_sci_set_attributes,
- .stop_remote_tx = NULL,
- .start_remote_tx = NULL,
.mode = TERMIOS_IRQ_DRIVEN
};
diff --git a/c/src/lib/libbsp/sparc/leon3/console/console.c b/c/src/lib/libbsp/sparc/leon3/console/console.c
index 9012492..513d45d 100644
--- a/c/src/lib/libbsp/sparc/leon3/console/console.c
+++ b/c/src/lib/libbsp/sparc/leon3/console/console.c
@@ -131,6 +131,7 @@ rtems_device_driver console_initialize(
major,
minor,
handler,
+ NULL,
leon3_console_get_uart(syscon_uart_index)
);
if (status != RTEMS_SUCCESSFUL)
@@ -147,6 +148,7 @@ rtems_device_driver console_initialize(
major,
minor,
handler,
+ NULL,
leon3_console_get_uart(syscon_uart_index)
);
}
diff --git a/cpukit/libcsupport/include/rtems/termiostypes.h b/cpukit/libcsupport/include/rtems/termiostypes.h
index 6339456..045a91f 100644
--- a/cpukit/libcsupport/include/rtems/termiostypes.h
+++ b/cpukit/libcsupport/include/rtems/termiostypes.h
@@ -144,6 +144,18 @@ typedef struct {
);

/**
+ * @brief Termios device mode.
+ */
+ rtems_termios_device_mode mode;
+} rtems_termios_device_handler;
+
+/**
+ * @brief Termios device flow control handler.
+ *
+ * @see rtems_termios_device_install().
+ */
+typedef struct {
+ /**
* @brief Indicate to stop remote transmitter.
*
* @param[in] tty The Termios control.
@@ -160,12 +172,7 @@ typedef struct {
* @see rtems_termios_get_device_context().
*/
void (*start_remote_tx)(struct rtems_termios_tty *tty);
-
- /**
- * @brief Termios device mode.
- */
- rtems_termios_device_mode mode;
-} rtems_termios_device_handler;
+} rtems_termios_device_flow;

/**
* @brief Termios device node for installed devices.
@@ -177,6 +184,7 @@ typedef struct rtems_termios_device_node {
rtems_device_major_number major;
rtems_device_minor_number minor;
const rtems_termios_device_handler *handler;
+ const rtems_termios_device_flow *flow;
void *context;
struct rtems_termios_tty *tty;
} rtems_termios_device_node;
@@ -254,6 +262,11 @@ typedef struct rtems_termios_tty {
*/
rtems_termios_device_handler handler;

+ /**
+ * @brief The device flow control handler.
+ */
+ rtems_termios_device_flow flow;
+
volatile unsigned int flow_ctrl;
unsigned int lowwater,highwater;

@@ -295,11 +308,14 @@ typedef struct rtems_termios_tty {
* @brief Installs a Termios device.
*
* @param[in] device_file If not @c NULL, then a device file for the specified
- * major and minor number will be created.
+ * major and minor number will be created.
* @param[in] major The device major number of the corresponding device driver.
* @param[in] minor The device minor number of the corresponding device driver.
* @param[in] handler The device handler. It must be persistent throughout the
* installed time of the device.
+ * @param[in] flow The device flow control handler. The device flow control
+ * handler are optional and may be @c NULL. If present must be persistent
+ * throughout the installed time of the device.
* @param[in] context The device context. It must be persistent throughout the
* installed time of the device.
*
@@ -307,17 +323,18 @@ typedef struct rtems_termios_tty {
* @retval RTEMS_NO_MEMORY Not enough memory to create a device node.
* @retval RTEMS_UNSATISFIED Creation of the device file failed.
* @retval RTEMS_RESOURCE_IN_USE There exists a device node for this major and
- * minor number pair.
+ * minor number pair.
* @retval RTEMS_INCORRECT_STATE Termios is not initialized.
*
* @see rtems_termios_device_remove(), rtems_termios_device_open(),
- * rtems_termios_device_close() and rtems_termios_get_device_context().
+ * rtems_termios_device_close() and rtems_termios_get_device_context().
*/
rtems_status_code rtems_termios_device_install(
const char *device_file,
rtems_device_major_number major,
rtems_device_minor_number minor,
const rtems_termios_device_handler *handler,
+ const rtems_termios_device_flow *flow,
void *context
);

diff --git a/cpukit/libcsupport/src/termios.c b/cpukit/libcsupport/src/termios.c
index 52171a1..6119b22 100644
--- a/cpukit/libcsupport/src/termios.c
+++ b/cpukit/libcsupport/src/termios.c
@@ -133,6 +133,7 @@ rtems_status_code rtems_termios_device_install(
rtems_device_major_number major,
rtems_device_minor_number minor,
const rtems_termios_device_handler *handler,
+ const rtems_termios_device_flow *flow,
void *context
)
{
@@ -148,6 +149,7 @@ rtems_status_code rtems_termios_device_install(
new_device_node->major = major;
new_device_node->minor = minor;
new_device_node->handler = handler;
+ new_device_node->flow = flow;
new_device_node->context = context;
new_device_node->tty = NULL;

@@ -458,6 +460,11 @@ rtems_termios_open_tty(
if (device_node != NULL) {
device_node->tty = tty;
tty->handler = *device_node->handler;
+
+ if (device_node->flow != NULL) {
+ tty->flow = *device_node->flow;
+ }
+
tty->device_node = device_node;
tty->device_context = device_node->context;
memset(&tty->device, 0, sizeof(tty->device));
@@ -472,9 +479,9 @@ rtems_termios_open_tty(
rtems_termios_callback_write : NULL;
tty->handler.set_attributes = callbacks->setAttributes != NULL ?
rtems_termios_callback_setAttributes : NULL;
- tty->handler.stop_remote_tx = callbacks->stopRemoteTx != NULL ?
+ tty->flow.stop_remote_tx = callbacks->stopRemoteTx != NULL ?
rtems_termios_callback_stopRemoteTx : NULL;
- tty->handler.start_remote_tx = callbacks->startRemoteTx != NULL ?
+ tty->flow.start_remote_tx = callbacks->startRemoteTx != NULL ?
rtems_termios_callback_startRemoteTx : NULL;
tty->handler.mode = callbacks->outputUsesInterrupts;
tty->device_context = NULL;
@@ -818,8 +825,8 @@ termios_set_flowctrl(struct rtems_termios_tty *tty)

/* restart remote Tx, if it was stopped */
if ((tty->flow_ctrl & FL_IRTSOFF) &&
- (tty->handler.start_remote_tx != NULL)) {
- tty->handler.start_remote_tx(tty);
+ (tty->flow.start_remote_tx != NULL)) {
+ tty->flow.start_remote_tx(tty);
}
tty->flow_ctrl &= ~(FL_IRTSOFF);
}
@@ -1444,8 +1451,8 @@ fillBufferQueue (struct rtems_termios_tty *tty)
} else if (tty->flow_ctrl & FL_MDRTS) {
tty->flow_ctrl &= ~FL_IRTSOFF;
/* activate RTS line */
- if (tty->handler.start_remote_tx != NULL) {
- tty->handler.start_remote_tx(tty);
+ if (tty->flow.start_remote_tx != NULL) {
+ tty->flow.start_remote_tx(tty);
}
}
}
@@ -1624,8 +1631,8 @@ rtems_termios_enqueue_raw_characters (void *ttyp, const char *buf, int len)
} else if ((tty->flow_ctrl & (FL_MDRTS | FL_IRTSOFF)) == (FL_MDRTS) ) {
tty->flow_ctrl |= FL_IRTSOFF;
/* deactivate RTS line */
- if (tty->handler.stop_remote_tx != NULL) {
- tty->handler.stop_remote_tx(tty);
+ if (tty->flow.stop_remote_tx != NULL) {
+ tty->flow.stop_remote_tx(tty);
}
}
}
diff --git a/doc/bsp_howto/console.t b/doc/bsp_howto/console.t
index e35ca36..a165f72 100644
--- a/doc/bsp_howto/console.t
+++ b/doc/bsp_howto/console.t
@@ -489,6 +489,7 @@ rtems_device_driver console_initialize(
major,
minor,
handler,
+ NULL,
ctx
);
if (sc != RTEMS_SUCCESSFUL) @{
diff --git a/testsuites/libtests/termios01/init.c b/testsuites/libtests/termios01/init.c
index d1de3f8..080363f 100644
--- a/testsuites/libtests/termios01/init.c
+++ b/testsuites/libtests/termios01/init.c
@@ -560,17 +560,31 @@ static void test_device_install_remove(void)

greedy = rtems_heap_greedy_allocate( NULL, 0 );

- sc = rtems_termios_device_install( "/", major, minor, &handler, NULL );
+ sc = rtems_termios_device_install( "/", major, minor, &handler, NULL, NULL );
rtems_test_assert( sc == RTEMS_NO_MEMORY );

rtems_heap_greedy_free( greedy );

rtems_test_assert( rtems_resource_snapshot_check( &snapshot ) );

- sc = rtems_termios_device_install( NULL, major, minor, &handler, NULL );
+ sc = rtems_termios_device_install(
+ NULL,
+ major,
+ minor,
+ &handler,
+ NULL,
+ NULL
+ );
rtems_test_assert( sc == RTEMS_SUCCESSFUL );

- sc = rtems_termios_device_install( NULL, major, minor, &handler, NULL );
+ sc = rtems_termios_device_install(
+ NULL,
+ major,
+ minor,
+ &handler,
+ NULL,
+ NULL
+ );
rtems_test_assert( sc == RTEMS_RESOURCE_IN_USE );

sc = rtems_termios_device_remove( NULL, major, minor );
@@ -578,7 +592,7 @@ static void test_device_install_remove(void)

rtems_test_assert( rtems_resource_snapshot_check( &snapshot ) );

- sc = rtems_termios_device_install( "/", major, minor, &handler, NULL );
+ sc = rtems_termios_device_install( "/", major, minor, &handler, NULL, NULL );
rtems_test_assert( sc == RTEMS_UNSATISFIED );

rtems_test_assert( rtems_resource_snapshot_check( &snapshot ) );
@@ -586,7 +600,14 @@ static void test_device_install_remove(void)
sc = rtems_termios_device_remove( NULL, major, minor );
rtems_test_assert( sc == RTEMS_INVALID_ID );

- sc = rtems_termios_device_install( &dev[0], major, minor, &handler, NULL );
+ sc = rtems_termios_device_install(
+ &dev[0],
+ major,
+ minor,
+ &handler,
+ NULL,
+ NULL
+ );
rtems_test_assert( sc == RTEMS_SUCCESSFUL );

sc = rtems_termios_device_remove( "/barfoo", major, minor );
@@ -638,7 +659,14 @@ static void test_first_open_error(void)

rtems_resource_snapshot_take( &snapshot );

- sc = rtems_termios_device_install( &dev[0], major, minor, &handler, &done );
+ sc = rtems_termios_device_install(
+ &dev[0],
+ major,
+ minor,
+ &handler,
+ NULL,
+ &done
+ );
rtems_test_assert( sc == RTEMS_SUCCESSFUL );

memset( &iop, 0, sizeof( iop ) );
@@ -689,7 +717,14 @@ static void test_set_attributes_error(void)

rtems_resource_snapshot_take( &snapshot );

- sc = rtems_termios_device_install( &dev[0], major, minor, &handler, &done );
+ sc = rtems_termios_device_install(
+ &dev[0],
+ major,
+ minor,
+ &handler,
+ NULL,
+ &done
+ );
rtems_test_assert( sc == RTEMS_SUCCESSFUL );

memset( &iop, 0, sizeof( iop ) );
--
1.8.4.5
Sebastian Huber
2014-10-07 14:36:29 UTC
Permalink
Call rtems_termios_dequeue_characters() only in case all characters of
the last write handler invocation have been transmitted. This avoids
problems with pppstart() since the start line discipline does not know
how many characters have been dequeued and assumes the maximum.
---
c/src/libchip/serial/ns16550-context.c | 53 +++++++++++++++++++++++-----------
c/src/libchip/serial/ns16550.h | 5 +++-
2 files changed, 40 insertions(+), 18 deletions(-)

diff --git a/c/src/libchip/serial/ns16550-context.c b/c/src/libchip/serial/ns16550-context.c
index a812271..0b5d1b05 100644
--- a/c/src/libchip/serial/ns16550-context.c
+++ b/c/src/libchip/serial/ns16550-context.c
@@ -162,6 +162,24 @@ bool ns16550_probe(rtems_termios_device_context *base)
return true;
}

+static size_t ns16550_write_to_fifo(
+ const ns16550_context *ctx,
+ const char *buf,
+ size_t len
+)
+{
+ uint32_t port = ctx->port;
+ ns16550_set_reg set = ctx->set_reg;
+ size_t out = len > SP_FIFO_SIZE ? SP_FIFO_SIZE : len;
+ size_t i;
+
+ for (i = 0; i < out; ++i) {
+ (*set)(port, NS16550_TRANSMIT_BUFFER, buf[i]);
+ }
+
+ return out;
+}
+
#if defined(BSP_FEATURE_IRQ_EXTENSION) || defined(BSP_FEATURE_IRQ_LEGACY)

/**
@@ -190,15 +208,20 @@ static void ns16550_isr(void *arg)
/* Enqueue fetched characters */
rtems_termios_enqueue_raw_characters(tty, buf, i);

- /* Check if we can dequeue transmitted characters */
- if (ctx->transmit_fifo_chars > 0
- && (get( port, NS16550_LINE_STATUS) & SP_LSR_THOLD) != 0) {
+ /* Do transmit */
+ if (ctx->out_total > 0
+ && (get(port, NS16550_LINE_STATUS) & SP_LSR_THOLD) != 0) {
+ size_t current = ctx->out_current;

- /* Dequeue transmitted characters */
- rtems_termios_dequeue_characters(
- tty,
- ctx->transmit_fifo_chars
- );
+ ctx->out_buf += current;
+ ctx->out_remaining -= current;
+
+ if (ctx->out_remaining > 0) {
+ ctx->out_current =
+ ns16550_write_to_fifo(ctx, ctx->out_buf, ctx->out_remaining);
+ } else {
+ rtems_termios_dequeue_characters(tty, ctx->out_total);
+ }
}
} while ((get( port, NS16550_INTERRUPT_ID) & SP_IID_0) == 0);
}
@@ -577,18 +600,14 @@ static void ns16550_write_support_int(
)
{
ns16550_context *ctx = (ns16550_context *) base;
- uint32_t port = ctx->port;
- ns16550_set_reg set = ctx->set_reg;
- int i = 0;
- int out = len > SP_FIFO_SIZE ? SP_FIFO_SIZE : len;

- for (i = 0; i < out; ++i) {
- set( port, NS16550_TRANSMIT_BUFFER, buf [i]);
- }
+ ctx->out_total = len;

- ctx->transmit_fifo_chars = out;
+ if (len > 0) {
+ ctx->out_remaining = len;
+ ctx->out_buf = buf;
+ ctx->out_current = ns16550_write_to_fifo(ctx, buf, len);

- if (out > 0) {
ns16550_enable_interrupts(ctx, NS16550_ENABLE_ALL_INTR);
} else {
ns16550_enable_interrupts(ctx, NS16550_ENABLE_ALL_INTR_EXCEPT_TX);
diff --git a/c/src/libchip/serial/ns16550.h b/c/src/libchip/serial/ns16550.h
index ef1f9f9..0b05fe3 100644
--- a/c/src/libchip/serial/ns16550.h
+++ b/c/src/libchip/serial/ns16550.h
@@ -70,7 +70,10 @@ typedef struct {
uint32_t initial_baud;
bool has_fractional_divider_register;
uint8_t modem_control;
- size_t transmit_fifo_chars;
+ size_t out_total;
+ size_t out_remaining;
+ size_t out_current;
+ const char *out_buf;
} ns16550_context;

extern const rtems_termios_device_handler ns16550_handler_interrupt;
--
1.8.4.5
Sebastian Huber
2014-10-07 14:36:30 UTC
Permalink
---
c/src/libchip/serial/ns16550-context.c | 130 ++++++++++++++++++++++++++++++---
c/src/libchip/serial/ns16550.h | 2 +
2 files changed, 120 insertions(+), 12 deletions(-)

diff --git a/c/src/libchip/serial/ns16550-context.c b/c/src/libchip/serial/ns16550-context.c
index 0b5d1b05..00ad89c 100644
--- a/c/src/libchip/serial/ns16550-context.c
+++ b/c/src/libchip/serial/ns16550-context.c
@@ -98,6 +98,26 @@ static void ns16550_enable_interrupts(
(*ctx->set_reg)(ctx->port, NS16550_INTERRUPT_ENABLE, mask);
}

+static void ns16550_clear_and_set_interrupts(
+ ns16550_context *ctx,
+ uint8_t clear,
+ uint8_t set
+)
+{
+ rtems_interrupt_lock_context lock_context;
+ ns16550_get_reg get_reg = ctx->get_reg;
+ ns16550_set_reg set_reg = ctx->set_reg;
+ uintptr_t port = ctx->port;
+ uint8_t val;
+
+ rtems_termios_device_lock_acquire(&ctx->base, &lock_context);
+ val = (*get_reg)(port, NS16550_INTERRUPT_ENABLE);
+ val &= ~clear;
+ val |= set;
+ (*set_reg)(port, NS16550_INTERRUPT_ENABLE, val);
+ rtems_termios_device_lock_release(&ctx->base, &lock_context);
+}
+
/*
* ns16550_probe
*/
@@ -180,8 +200,6 @@ static size_t ns16550_write_to_fifo(
return out;
}

-#if defined(BSP_FEATURE_IRQ_EXTENSION) || defined(BSP_FEATURE_IRQ_LEGACY)
-
/**
* @brief Process interrupt.
*/
@@ -225,7 +243,58 @@ static void ns16550_isr(void *arg)
}
} while ((get( port, NS16550_INTERRUPT_ID) & SP_IID_0) == 0);
}
-#endif
+
+static void ns16550_isr_task(void *arg)
+{
+ rtems_termios_tty *tty = arg;
+ ns16550_context *ctx = rtems_termios_get_device_context(tty);
+ uint8_t status = (*ctx->get_reg)(ctx->port, NS16550_LINE_STATUS);
+
+ if ((status & SP_LSR_RDY) != 0) {
+ ns16550_clear_and_set_interrupts(ctx, SP_INT_RX_ENABLE, 0);
+ rtems_termios_rxirq_occured(tty);
+ }
+
+ if (ctx->out_total > 0 && (status & SP_LSR_THOLD) != 0) {
+ size_t current = ctx->out_current;
+
+ ctx->out_buf += current;
+ ctx->out_remaining -= current;
+
+ if (ctx->out_remaining > 0) {
+ ctx->out_current =
+ ns16550_write_to_fifo(ctx, ctx->out_buf, ctx->out_remaining);
+ } else {
+ size_t done = ctx->out_total;
+
+ ctx->out_total = 0;
+ ns16550_clear_and_set_interrupts(ctx, SP_INT_TX_ENABLE, 0);
+ rtems_termios_dequeue_characters(tty, done);
+ }
+ }
+}
+
+static int ns16550_read_task(rtems_termios_device_context *base)
+{
+ ns16550_context *ctx = (ns16550_context *) base;
+ uint32_t port = ctx->port;
+ ns16550_get_reg get = ctx->get_reg;
+ char buf[SP_FIFO_SIZE];
+ int i;
+
+ for (i = 0; i < SP_FIFO_SIZE; ++i) {
+ if ((get(port, NS16550_LINE_STATUS) & SP_LSR_RDY) != 0) {
+ buf[i] = (char) get(port, NS16550_RECEIVE_BUFFER);
+ } else {
+ break;
+ }
+ }
+
+ rtems_termios_enqueue_raw_characters(ctx->tty, buf, i);
+ ns16550_clear_and_set_interrupts(ctx, 0, SP_INT_RX_ENABLE);
+
+ return -1;
+}

/*
* ns16550_initialize_interrupts
@@ -234,7 +303,8 @@ static void ns16550_isr(void *arg)
*/
static void ns16550_initialize_interrupts(
struct rtems_termios_tty *tty,
- ns16550_context *ctx
+ ns16550_context *ctx,
+ void (*isr)(void *)
)
{
#ifdef BSP_FEATURE_IRQ_EXTENSION
@@ -244,7 +314,7 @@ static void ns16550_initialize_interrupts(
ctx->irq,
"NS16550",
RTEMS_INTERRUPT_SHARED,
- ns16550_isr,
+ isr,
tty
);
if (sc != RTEMS_SUCCESSFUL) {
@@ -259,7 +329,7 @@ static void ns16550_initialize_interrupts(
#ifdef BSP_FEATURE_IRQ_LEGACY_SHARED_HANDLER_SUPPORT
rtems_irq_connect_data cd = {
ctx->irq,
- ns16550_isr,
+ isr,
tty,
NULL,
NULL,
@@ -270,7 +340,7 @@ static void ns16550_initialize_interrupts(
#else
rtems_irq_connect_data cd = {
ctx->irq,
- ns16550_isr,
+ isr,
tty,
NULL,
NULL,
@@ -300,11 +370,16 @@ static bool ns16550_open(
{
ns16550_context *ctx = (ns16550_context *) base;

+ ctx->tty = tty;
+
/* Set initial baud */
rtems_termios_set_initial_baud(tty, ctx->initial_baud);

if (tty->handler.mode == TERMIOS_IRQ_DRIVEN) {
- ns16550_initialize_interrupts(tty, ctx);
+ ns16550_initialize_interrupts(tty, ctx, ns16550_isr);
+ ns16550_enable_interrupts(ctx, NS16550_ENABLE_ALL_INTR_EXCEPT_TX);
+ } else if (tty->handler.mode == TERMIOS_TASK_DRIVEN) {
+ ns16550_initialize_interrupts(tty, ctx, ns16550_isr_task);
ns16550_enable_interrupts(ctx, NS16550_ENABLE_ALL_INTR_EXCEPT_TX);
}

@@ -313,14 +388,15 @@ static bool ns16550_open(

static void ns16550_cleanup_interrupts(
struct rtems_termios_tty *tty,
- ns16550_context *ctx
+ ns16550_context *ctx,
+ void (*isr)(void *)
)
{
#if defined(BSP_FEATURE_IRQ_EXTENSION)
rtems_status_code sc = RTEMS_SUCCESSFUL;
sc = rtems_interrupt_handler_remove(
ctx->irq,
- ns16550_isr,
+ isr,
tty
);
if (sc != RTEMS_SUCCESSFUL) {
@@ -332,7 +408,7 @@ static void ns16550_cleanup_interrupts(
int rv = 0;
rtems_irq_connect_data cd = {
.name = ctx->irq,
- .hdl = ns16550_isr,
+ .hdl = isr,
.handle = tty
};
rv = BSP_remove_rtems_irq_handler(&cd);
@@ -359,7 +435,9 @@ static void ns16550_close(
ns16550_enable_interrupts(ctx, NS16550_DISABLE_ALL_INTR);

if (tty->handler.mode == TERMIOS_IRQ_DRIVEN) {
- ns16550_cleanup_interrupts(tty, ctx);
+ ns16550_cleanup_interrupts(tty, ctx, ns16550_isr);
+ } else if (tty->handler.mode == TERMIOS_TASK_DRIVEN) {
+ ns16550_cleanup_interrupts(tty, ctx, ns16550_isr_task);
}
}

@@ -614,6 +692,25 @@ static void ns16550_write_support_int(
}
}

+static void ns16550_write_support_task(
+ rtems_termios_device_context *base,
+ const char *buf,
+ size_t len
+)
+{
+ ns16550_context *ctx = (ns16550_context *) base;
+
+ ctx->out_total = len;
+
+ if (len > 0) {
+ ctx->out_remaining = len;
+ ctx->out_buf = buf;
+ ctx->out_current = ns16550_write_to_fifo(ctx, buf, len);
+
+ ns16550_clear_and_set_interrupts(ctx, 0, SP_INT_TX_ENABLE);
+ }
+}
+
/*
* ns16550_write_support_polled
*
@@ -694,3 +791,12 @@ const rtems_termios_device_handler ns16550_handler_polled = {
.set_attributes = ns16550_set_attributes,
.mode = TERMIOS_POLLED
};
+
+const rtems_termios_device_handler ns16550_handler_task = {
+ .first_open = ns16550_open,
+ .last_close = ns16550_close,
+ .poll_read = ns16550_read_task,
+ .write = ns16550_write_support_task,
+ .set_attributes = ns16550_set_attributes,
+ .mode = TERMIOS_TASK_DRIVEN
+};
diff --git a/c/src/libchip/serial/ns16550.h b/c/src/libchip/serial/ns16550.h
index 0b05fe3..19ac3f1 100644
--- a/c/src/libchip/serial/ns16550.h
+++ b/c/src/libchip/serial/ns16550.h
@@ -74,10 +74,12 @@ typedef struct {
size_t out_remaining;
size_t out_current;
const char *out_buf;
+ rtems_termios_tty *tty;
} ns16550_context;

extern const rtems_termios_device_handler ns16550_handler_interrupt;
extern const rtems_termios_device_handler ns16550_handler_polled;
+extern const rtems_termios_device_handler ns16550_handler_task;

extern const rtems_termios_device_flow ns16550_flow_rtscts;
extern const rtems_termios_device_flow ns16550_flow_dtrcts;
--
1.8.4.5
Sebastian Huber
2014-10-07 14:36:26 UTC
Permalink
Move interrupt lock to device context and expose only this structure to
the read, write and set attributes device handler. This makes these
device handler independent of the general Termios infrastructure
suitable for direct use in printk() support.
---
c/src/lib/libbsp/arm/tms570/console/tms570-sci.c | 74 ++++++-----
.../libbsp/arm/tms570/include/tms570-sci-driver.h | 1 +
c/src/lib/libbsp/sparc/leon3/console/console.c | 10 +-
.../libbsp/sparc/shared/include/apbuart_termios.h | 1 +
.../lib/libbsp/sparc/shared/uart/apbuart_termios.c | 45 ++++---
cpukit/libcsupport/include/rtems/termiostypes.h | 146 ++++++++++++++-------
cpukit/libcsupport/src/termios.c | 142 ++++++++++++--------
cpukit/libcsupport/src/termios_setbestbaud.c | 6 +-
cpukit/libnetworking/net/if_ppp.c | 2 +-
cpukit/libnetworking/net/ppp_tty.c | 5 +-
doc/bsp_howto/console.t | 38 +++---
testsuites/libtests/termios01/init.c | 52 +++++---
12 files changed, 325 insertions(+), 197 deletions(-)

diff --git a/c/src/lib/libbsp/arm/tms570/console/tms570-sci.c b/c/src/lib/libbsp/arm/tms570/console/tms570-sci.c
index 961754e..3f10300 100644
--- a/c/src/lib/libbsp/arm/tms570/console/tms570-sci.c
+++ b/c/src/lib/libbsp/arm/tms570/console/tms570-sci.c
@@ -26,7 +26,6 @@
#include <bspopts.h>
#include <termios.h>
#include <rtems/termiostypes.h>
-#include <libchip/sersupp.h>
#include <bsp/tms570-sci.h>
#include <bsp/tms570-sci-driver.h>
#include <rtems/console.h>
@@ -43,11 +42,13 @@
*/
const tms570_sci_context driver_context_table[] = {
{
+ .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("TMS570 SCI1"),
.device_name = "/dev/console",
.regs = &TMS570_SCI,
.irq = TMS570_IRQ_SCI_LEVEL_0,
},
{
+ .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("TMS570 SCI2"),
.device_name = "/dev/ttyS1",
.regs = &TMS570_SCI2,
.irq = TMS570_IRQ_SCI2_LEVEL_0,
@@ -104,7 +105,7 @@ rtems_device_driver console_initialize(
minor,
handler,
NULL,
- (void *) ctx
+ RTEMS_DECONST(rtems_termios_device_context *, &ctx->base)
);
if ( sc != RTEMS_SUCCESSFUL ) {
bsp_fatal(BSP_FATAL_CONSOLE_NO_DEV);
@@ -196,21 +197,21 @@ static int tms570_sci_transmitted_chars(tms570_sci_context * ctx)
*
* Sets attributes of the HW peripheral (parity, baud rate, etc.)
*
- * @param[in] tty rtems_termios_tty
+ * @param[in] base context of the driver
* @param[in] t termios driver
* @retval true peripheral setting is changed
*/
static bool tms570_sci_set_attributes(
- rtems_termios_tty *tty,
+ rtems_termios_device_context *base,
const struct termios *t
)
{
- tms570_sci_context *ctx = rtems_termios_get_device_context(tty);
+ tms570_sci_context *ctx = (tms570_sci_context *) base;
rtems_interrupt_lock_context lock_context;
int32_t bauddiv;
int32_t baudrate;

- rtems_termios_interrupt_lock_acquire(tty, &lock_context);
+ rtems_termios_device_lock_acquire(base, &lock_context);

ctx->regs->SCIGCR1 &= ~( (1<<7) | (1<<25) | (1<<24) );

@@ -245,7 +246,7 @@ static bool tms570_sci_set_attributes(

ctx->regs->SCIGCR1 |= (1<<7) | (1<<25) | (1<<24);

- rtems_termios_interrupt_lock_release(tty, &lock_context);
+ rtems_termios_device_lock_release(base, &lock_context);

return true;
}
@@ -300,18 +301,18 @@ static void tms570_sci_interrupt_handler(void * arg)
* TMS570 does not have write data buffer asociated with SCI
* so only one character can be written.
*
- * @param[in] tty rtems_termios_tty
+ * @param[in] base context of the driver
* @param[in] buf buffer of characters pending to send
* @param[in] len size of the buffer
* @retval Void
*/
static void tms570_sci_interrupt_write(
- rtems_termios_tty *tty,
+ rtems_termios_device_context *base,
const char *buf,
size_t len
)
{
- tms570_sci_context *ctx = rtems_termios_get_device_context(tty);
+ tms570_sci_context *ctx = (tms570_sci_context *) base;

if ( len > 0 ) {
/* start UART TX, this will result in an interrupt when done */
@@ -334,18 +335,18 @@ static void tms570_sci_interrupt_write(
* Blocking write function. Waits until HW peripheral is ready and then writes
* character to HW peripheral. Writes all characters in the buffer.
*
- * @param[in] tty rtems_termios_tty
+ * @param[in] base context of the driver
* @param[in] buf buffer of characters pending to send
* @param[in] len size of the buffer
* @retval Void
*/
static void tms570_sci_poll_write(
- rtems_termios_tty *tty,
- const char *buf,
- size_t n
+ rtems_termios_device_context *base,
+ const char *buf,
+ size_t n
)
{
- tms570_sci_context *ctx = rtems_termios_get_device_context(tty);
+ tms570_sci_context *ctx = (tms570_sci_context *) base;
size_t i;

/* Write */
@@ -394,13 +395,13 @@ static char TMS570_sci_read_char(
*
* check if there is recieved character to be read and reads it.
*
- * @param[in] tty rtems_termios_tty (context of the driver)
+ * @param[in] base context of the driver
* @retval -1 No character to be read
* @retval x Read character
*/
-static int tms570_sci_poll_read(rtems_termios_tty *tty)
+static int tms570_sci_poll_read(rtems_termios_device_context *base)
{
- tms570_sci_context *ctx = rtems_termios_get_device_context(tty);
+ tms570_sci_context *ctx = (tms570_sci_context *) base;

/* Check if a character is available */
if ( TMS570_sci_can_read_char(ctx) ) {
@@ -416,20 +417,24 @@ static int tms570_sci_poll_read(rtems_termios_tty *tty)
* initialization of the HW peripheral specified in contex of the driver.
* This function is called only once when opening the driver.
*
- * @param[in] tty context of the driver
+ * @param[in] tty Termios control
+ * @param[in] ctx context of the driver
+ * @param[in] term Termios attributes
* @param[in] args
* @retval false Error occured during initialization
* @retval true Driver is open and ready
*/
static bool tms570_sci_poll_first_open(
rtems_termios_tty *tty,
+ rtems_termios_device_context *ctx,
+ struct termios *term,
rtems_libio_open_close_args_t *args
)
{
bool ok;

- rtems_termios_set_best_baud(tty, TMS570_SCI_BAUD_RATE);
- ok = tms570_sci_set_attributes(tty, rtems_termios_get_termios(tty));
+ rtems_termios_set_best_baud(term, TMS570_SCI_BAUD_RATE);
+ ok = tms570_sci_set_attributes(ctx, term);
if ( !ok ) {
return false;
}
@@ -442,21 +447,24 @@ static bool tms570_sci_poll_first_open(
* calls tms570_sci_poll_first_open function.
* install and enables interrupts.
*
- * @param[in] tty context of the driver
+ * @param[in] tty Termios control
+ * @param[in] base context of the driver
* @param[in] args
* @retval false Error occured during initialization
* @retval true Driver is open and ready
*/
static bool tms570_sci_interrupt_first_open(
rtems_termios_tty *tty,
+ rtems_termios_device_context *base,
+ struct termios *term,
rtems_libio_open_close_args_t *args
)
{
- tms570_sci_context *ctx = rtems_termios_get_device_context(tty);
+ tms570_sci_context *ctx = (tms570_sci_context *) base;
rtems_status_code sc;
bool ret;

- ret = tms570_sci_poll_first_open(tty,args);
+ ret = tms570_sci_poll_first_open(tty, base, term, args);
if ( ret == false ) {
return false;
}
@@ -471,20 +479,22 @@ static bool tms570_sci_interrupt_first_open(
if ( sc != RTEMS_SUCCESSFUL ) {
return false;
}
- tms570_sci_enable_interrupts(rtems_termios_get_device_context(tty));
+ tms570_sci_enable_interrupts(ctx);
return true;
}

/**
* @brief closes sci peripheral
*
- * @param[in] tty context of the driver
+ * @param[in] tty Termios control
+ * @param[in] base context of the driver
* @param[in] args
* @retval false Error occured during initialization
* @retval true Driver is open and ready
*/
static void tms570_sci_poll_last_close(
rtems_termios_tty *tty,
+ rtems_termios_device_context *base,
rtems_libio_open_close_args_t *args
)
{
@@ -496,23 +506,25 @@ static void tms570_sci_poll_last_close(
*
* calls tms570_sci_poll_last_close and disables interrupts
*
- * @param[in] tty context of the driver
+ * @param[in] tty Termios control
+ * @param[in] base context of the driver
* @param[in] args
* @retval false Error occured during initialization
* @retval true Driver is open and ready
*/
static void tms570_sci_interrupt_last_close(
rtems_termios_tty *tty,
+ rtems_termios_device_context *base,
rtems_libio_open_close_args_t *args
)
{
- tms570_sci_context *ctx = rtems_termios_get_device_context(tty);
+ tms570_sci_context *ctx = (tms570_sci_context *) base;
rtems_interrupt_lock_context lock_context;

/* Turn off RX interrupts */
- rtems_termios_interrupt_lock_acquire(tty, &lock_context);
+ rtems_termios_device_lock_acquire(base, &lock_context);
tms570_sci_disable_interrupts(ctx);
- rtems_termios_interrupt_lock_release(tty, &lock_context);
+ rtems_termios_device_lock_release(base, &lock_context);

/* Flush device */
while ( ( ctx->regs->SCIFLR & (1<<11) ) > 0 ) {
@@ -522,7 +534,7 @@ static void tms570_sci_interrupt_last_close(
/* uninstall ISR */
rtems_interrupt_handler_remove(ctx->irq, tms570_sci_interrupt_handler, tty);

- tms570_sci_poll_last_close(tty,args);
+ tms570_sci_poll_last_close(tty, base, args);
}

/**
diff --git a/c/src/lib/libbsp/arm/tms570/include/tms570-sci-driver.h b/c/src/lib/libbsp/arm/tms570/include/tms570-sci-driver.h
index 5f38908..f32eaea 100644
--- a/c/src/lib/libbsp/arm/tms570/include/tms570-sci-driver.h
+++ b/c/src/lib/libbsp/arm/tms570/include/tms570-sci-driver.h
@@ -36,6 +36,7 @@ extern "C" {

/* Low-level driver specific data structure */
typedef struct {
+ rtems_termios_device_context base;
const char *device_name;
volatile tms570_sci_t *regs;
int tx_chars_in_hw;
diff --git a/c/src/lib/libbsp/sparc/leon3/console/console.c b/c/src/lib/libbsp/sparc/leon3/console/console.c
index 513d45d..35767ce 100644
--- a/c/src/lib/libbsp/sparc/leon3/console/console.c
+++ b/c/src/lib/libbsp/sparc/leon3/console/console.c
@@ -36,7 +36,7 @@ int syscon_uart_index __attribute__((weak)) = 0;
static struct apbuart_context apbuarts[BSP_NUMBER_OF_TERMIOS_PORTS];
static int uarts = 0;

-static struct apbuart_context *leon3_console_get_uart(int minor)
+static rtems_termios_device_context *leon3_console_get_context(int minor)
{
struct apbuart_context *uart;

@@ -45,7 +45,9 @@ static struct apbuart_context *leon3_console_get_uart(int minor)
else
uart = &apbuarts[minor - 1];

- return uart;
+ rtems_termios_device_context_initialize(&uart->base, "APBUART");
+
+ return &uart->base;
}

/* AMBA PP find routine. Extract AMBA PnP information into data structure. */
@@ -132,7 +134,7 @@ rtems_device_driver console_initialize(
minor,
handler,
NULL,
- leon3_console_get_uart(syscon_uart_index)
+ leon3_console_get_context(syscon_uart_index)
);
if (status != RTEMS_SUCCESSFUL)
bsp_fatal(LEON3_FATAL_CONSOLE_REGISTER_DEV);
@@ -149,7 +151,7 @@ rtems_device_driver console_initialize(
minor,
handler,
NULL,
- leon3_console_get_uart(syscon_uart_index)
+ leon3_console_get_context(syscon_uart_index)
);
}

diff --git a/c/src/lib/libbsp/sparc/shared/include/apbuart_termios.h b/c/src/lib/libbsp/sparc/shared/include/apbuart_termios.h
index ba5f049..40377c1 100644
--- a/c/src/lib/libbsp/sparc/shared/include/apbuart_termios.h
+++ b/c/src/lib/libbsp/sparc/shared/include/apbuart_termios.h
@@ -22,6 +22,7 @@ extern "C" {
#endif /* __cplusplus */

struct apbuart_context {
+ rtems_termios_device_context base;
struct apbuart_regs *regs;
unsigned int freq_hz;
rtems_vector_number irq;
diff --git a/c/src/lib/libbsp/sparc/shared/uart/apbuart_termios.c b/c/src/lib/libbsp/sparc/shared/uart/apbuart_termios.c
index dd3ca5d..05bd608 100644
--- a/c/src/lib/libbsp/sparc/shared/uart/apbuart_termios.c
+++ b/c/src/lib/libbsp/sparc/shared/uart/apbuart_termios.c
@@ -41,12 +41,12 @@ static void apbuart_isr(void *arg)
}

static void apbuart_write_support(
- rtems_termios_tty *tty,
+ rtems_termios_device_context *base,
const char *buf,
size_t len
)
{
- struct apbuart_context *uart = rtems_termios_get_device_context(tty);
+ struct apbuart_context *uart = (struct apbuart_context *) base;
int sending;

if (len > 0) {
@@ -69,12 +69,12 @@ static void apbuart_write_support(
}

static void apbuart_write_polled(
- rtems_termios_tty *tty,
+ rtems_termios_device_context *base,
const char *buf,
size_t len
)
{
- struct apbuart_context *uart = rtems_termios_get_device_context(tty);
+ struct apbuart_context *uart = (struct apbuart_context *) base;
size_t nwrite = 0;

while (nwrite < len) {
@@ -83,19 +83,19 @@ static void apbuart_write_polled(
}
}

-static int apbuart_poll_read(rtems_termios_tty *tty)
+static int apbuart_poll_read(rtems_termios_device_context *base)
{
- struct apbuart_context *uart = rtems_termios_get_device_context(tty);
+ struct apbuart_context *uart = (struct apbuart_context *) base;

return apbuart_inbyte_nonblocking(uart->regs);
}

static bool apbuart_set_attributes(
- rtems_termios_tty *tty,
+ rtems_termios_device_context *base,
const struct termios *t
)
{
- struct apbuart_context *uart = rtems_termios_get_device_context(tty);
+ struct apbuart_context *uart = (struct apbuart_context *) base;
rtems_interrupt_lock_context lock_context;
unsigned int scaler;
unsigned int ctrl;
@@ -112,7 +112,7 @@ static bool apbuart_set_attributes(
break;
}

- rtems_termios_interrupt_lock_acquire(tty, &lock_context);
+ rtems_termios_device_lock_acquire(base, &lock_context);

/* Read out current value */
ctrl = uart->regs->ctrl;
@@ -145,7 +145,7 @@ static bool apbuart_set_attributes(
/* Update new settings */
uart->regs->ctrl = ctrl;

- rtems_termios_interrupt_lock_release(tty, &lock_context);
+ rtems_termios_device_lock_release(base, &lock_context);

/* Baud rate */
baud = rtems_termios_baud_to_number(t->c_cflag);
@@ -161,23 +161,25 @@ static bool apbuart_set_attributes(
}

static void apbuart_set_best_baud(
- rtems_termios_tty *tty,
- const struct apbuart_context *uart
+ const struct apbuart_context *uart,
+ struct termios *term
)
{
uint32_t baud = (uart->freq_hz * 10) / ((uart->regs->scaler * 10 + 5) * 8);

- rtems_termios_set_best_baud(tty, baud);
+ rtems_termios_set_best_baud(term, baud);
}

static bool apbuart_first_open_polled(
rtems_termios_tty *tty,
+ rtems_termios_device_context *base,
+ struct termios *term,
rtems_libio_open_close_args_t *args
)
{
- struct apbuart_context *uart = rtems_termios_get_device_context(tty);
+ struct apbuart_context *uart = (struct apbuart_context *) base;

- apbuart_set_best_baud(tty, uart);
+ apbuart_set_best_baud(uart, term);

/* Initialize UART on opening */
uart->regs->ctrl |= APBUART_CTRL_RE | APBUART_CTRL_TE;
@@ -188,13 +190,15 @@ static bool apbuart_first_open_polled(

static bool apbuart_first_open_interrupt(
rtems_termios_tty *tty,
+ rtems_termios_device_context *base,
+ struct termios *term,
rtems_libio_open_close_args_t *args
)
{
- struct apbuart_context *uart = rtems_termios_get_device_context(tty);
+ struct apbuart_context *uart = (struct apbuart_context *) base;
rtems_status_code sc;

- apbuart_set_best_baud(tty, uart);
+ apbuart_set_best_baud(uart, term);

/* Register Interrupt handler */
sc = rtems_interrupt_handler_install(uart->irq, "console",
@@ -217,16 +221,17 @@ static bool apbuart_first_open_interrupt(

static void apbuart_last_close_interrupt(
rtems_termios_tty *tty,
+ rtems_termios_device_context *base,
rtems_libio_open_close_args_t *args
)
{
- struct apbuart_context *uart = rtems_termios_get_device_context(tty);
+ struct apbuart_context *uart = (struct apbuart_context *) base;
rtems_interrupt_lock_context lock_context;

/* Turn off RX interrupts */
- rtems_termios_interrupt_lock_acquire(tty, &lock_context);
+ rtems_termios_device_lock_acquire(base, &lock_context);
uart->regs->ctrl &= ~(APBUART_CTRL_RI);
- rtems_termios_interrupt_lock_release(tty, &lock_context);
+ rtems_termios_device_lock_release(base, &lock_context);

/**** Flush device ****/
while (uart->sending) {
diff --git a/cpukit/libcsupport/include/rtems/termiostypes.h b/cpukit/libcsupport/include/rtems/termiostypes.h
index 045a91f..71be95f 100644
--- a/cpukit/libcsupport/include/rtems/termiostypes.h
+++ b/cpukit/libcsupport/include/rtems/termiostypes.h
@@ -63,6 +63,42 @@ typedef enum {
struct rtems_termios_tty;

/**
+ * @brief Termios device context.
+ *
+ * @see RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER(),
+ * rtems_termios_device_context_initialize() and
+ * rtems_termios_device_install().
+ */
+typedef struct rtems_termios_device_context {
+ rtems_interrupt_lock interrupt_lock;
+} rtems_termios_device_context;
+
+/**
+ * @brief Initializes a device context.
+ *
+ * @param[in] context The Termios device context.
+ * @param[in] name The name for the interrupt lock. This name must be a
+ * string persistent throughout the life time of this lock. The name is only
+ * used if profiling is enabled.
+ */
+RTEMS_INLINE_ROUTINE void rtems_termios_device_context_initialize(
+ rtems_termios_device_context *context,
+ const char *name
+)
+{
+ rtems_interrupt_lock_initialize( &context->interrupt_lock, name );
+}
+
+/**
+ * @brief Initializer for static initialization of Termios device contexts.
+ *
+ * @param name The name for the interrupt lock. It must be a string. The name
+ * is only used if profiling is enabled.
+ */
+#define RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER( name ) \
+ { RTEMS_INTERRUPT_LOCK_INITIALIZER( name ) }
+
+/**
* @brief Termios device handler.
*
* @see rtems_termios_device_install().
@@ -71,18 +107,24 @@ typedef struct {
/**
* @brief First open of this device.
*
- * @param[in] tty The Termios control.
+ * @param[in] tty The Termios control. This parameter may be passed to
+ * interrupt service routines since it must be provided for the
+ * rtems_termios_enqueue_raw_characters() and
+ * rtems_termios_dequeue_characters() functions.
+ * @param[in] context The Termios device context.
+ * @param[in] term The current Termios attributes.
* @param[in] args The open/close arguments. This is parameter provided to
* support legacy drivers. It must not be used by new drivers.
*
* @retval true Successful operation.
* @retval false Cannot open device.
*
- * @see rtems_termios_get_device_context(), rtems_termios_set_best_baud() and
- * rtems_termios_get_termios().
+ * @see rtems_termios_get_device_context() and rtems_termios_set_best_baud().
*/
bool (*first_open)(
struct rtems_termios_tty *tty,
+ rtems_termios_device_context *context,
+ struct termios *term,
rtems_libio_open_close_args_t *args
);

@@ -90,13 +132,13 @@ typedef struct {
* @brief Last close of this device.
*
* @param[in] tty The Termios control.
+ * @param[in] context The Termios device context.
* @param[in] args The open/close arguments. This is parameter provided to
* support legacy drivers. It must not be used by new drivers.
- *
- * @see rtems_termios_get_device_context().
*/
void (*last_close)(
struct rtems_termios_tty *tty,
+ rtems_termios_device_context *context,
rtems_libio_open_close_args_t *args
);

@@ -106,41 +148,39 @@ typedef struct {
* In case mode is TERMIOS_IRQ_DRIVEN or TERMIOS_TASK_DRIVEN, then data is
* received via rtems_termios_enqueue_raw_characters().
*
- * @param[in] tty The Termios control.
+ * @param[in] context The Termios device context.
*
* @retval char The received data encoded as unsigned char.
* @retval -1 No data currently available.
- *
- * @see rtems_termios_get_device_context().
*/
- int (*poll_read)(struct rtems_termios_tty *tty);
+ int (*poll_read)(rtems_termios_device_context *context);

/**
* @brief Polled write in case mode is TERMIOS_POLLED or write support
* otherwise.
*
- * @param[in] tty The Termios control.
+ * @param[in] context The Termios device context.
* @param[in] buf The output buffer.
* @param[in] len The output buffer length in characters.
- *
- * @see rtems_termios_get_device_context().
*/
- void (*write)(struct rtems_termios_tty *tty, const char *buf, size_t len);
+ void (*write)(
+ rtems_termios_device_context *context,
+ const char *buf,
+ size_t len
+ );

/**
* @brief Set attributes after a Termios settings change.
*
- * @param[in] tty The Termios control.
+ * @param[in] context The Termios device context.
* @param[in] term The new Termios attributes.
*
* @retval true Successful operation.
* @retval false Invalid attributes.
- *
- * @see rtems_termios_get_device_context().
*/
bool (*set_attributes)(
- struct rtems_termios_tty *tty,
- const struct termios *term
+ rtems_termios_device_context *context,
+ const struct termios *term
);

/**
@@ -158,20 +198,16 @@ typedef struct {
/**
* @brief Indicate to stop remote transmitter.
*
- * @param[in] tty The Termios control.
- *
- * @see rtems_termios_get_device_context().
+ * @param[in] context The Termios device context.
*/
- void (*stop_remote_tx)(struct rtems_termios_tty *tty);
+ void (*stop_remote_tx)(rtems_termios_device_context *context);

/**
* @brief Indicate to start remote transmitter.
*
- * @param[in] tty The Termios control.
- *
- * @see rtems_termios_get_device_context().
+ * @param[in] context The Termios device context.
*/
- void (*start_remote_tx)(struct rtems_termios_tty *tty);
+ void (*start_remote_tx)(rtems_termios_device_context *context);
} rtems_termios_device_flow;

/**
@@ -185,7 +221,7 @@ typedef struct rtems_termios_device_node {
rtems_device_minor_number minor;
const rtems_termios_device_handler *handler;
const rtems_termios_device_flow *flow;
- void *context;
+ rtems_termios_device_context *context;
struct rtems_termios_tty *tty;
} rtems_termios_device_node;

@@ -258,6 +294,11 @@ typedef struct rtems_termios_tty {
rtems_termios_callbacks device;

/**
+ * @brief Context for legacy devices using the callbacks.
+ */
+ rtems_termios_device_context legacy_device_context;
+
+ /**
* @brief The device handler.
*/
rtems_termios_device_handler handler;
@@ -289,8 +330,6 @@ typedef struct rtems_termios_tty {
struct ttywakeup tty_rcv;
int tty_rcvwakeup;

- rtems_interrupt_lock interrupt_lock;
-
/**
* @brief Corresponding device node.
*/
@@ -298,10 +337,8 @@ typedef struct rtems_termios_tty {

/**
* @brief Context for device driver.
- *
- * @see rtems_termios_get_device_context().
*/
- void *device_context;
+ rtems_termios_device_context *device_context;
} rtems_termios_tty;

/**
@@ -335,7 +372,7 @@ rtems_status_code rtems_termios_device_install(
rtems_device_minor_number minor,
const rtems_termios_device_handler *handler,
const rtems_termios_device_flow *flow,
- void *context
+ rtems_termios_device_context *context
);

/**
@@ -382,6 +419,8 @@ rtems_status_code rtems_termios_device_close(void *arg);

/**
* @brief Returns the device context of an installed Termios device.
+ *
+ * @param[in] tty The Termios control.
*/
RTEMS_INLINE_ROUTINE void *rtems_termios_get_device_context(
const rtems_termios_tty *tty
@@ -391,16 +430,33 @@ RTEMS_INLINE_ROUTINE void *rtems_termios_get_device_context(
}

/**
- * @brief Returns the Termios structure.
+ * @brief Acquires the device lock.
*
- * It can be used for example in the first open handler to adjust or obtain the
- * initial attributes.
+ * @param[in] context The device context.
+ * @param[in] lock_context The local interrupt lock context for an acquire and
+ * release pair.
*/
-RTEMS_INLINE_ROUTINE struct termios *rtems_termios_get_termios(
- rtems_termios_tty *tty
+RTEMS_INLINE_ROUTINE void rtems_termios_device_lock_acquire(
+ rtems_termios_device_context *context,
+ rtems_interrupt_lock_context *lock_context
)
{
- return &tty->termios;
+ rtems_interrupt_lock_acquire( &context->interrupt_lock, lock_context );
+}
+
+/**
+ * @brief Releases the device lock.
+ *
+ * @param[in] context The device context.
+ * @param[in] lock_context The local interrupt lock context for an acquire and
+ * release pair.
+ */
+RTEMS_INLINE_ROUTINE void rtems_termios_device_lock_release(
+ rtems_termios_device_context *context,
+ rtems_interrupt_lock_context *lock_context
+)
+{
+ rtems_interrupt_lock_release( &context->interrupt_lock, lock_context );
}

/**
@@ -409,12 +465,12 @@ RTEMS_INLINE_ROUTINE struct termios *rtems_termios_get_termios(
* The valid Termios baud values are between 0 and 460800. The Termios baud
* value is chosen which minimizes the difference to the value specified.
*
- * @param[in] tty The Termios control.
+ * @param[in] term The Termios attributes.
* @param[in] baud The current baud setting of the device.
*/
void rtems_termios_set_best_baud(
- rtems_termios_tty *tty,
- uint32_t baud
+ struct termios *term,
+ uint32_t baud
);

struct rtems_termios_linesw {
@@ -498,12 +554,6 @@ int rtems_termios_set_initial_baud(
rtems_termios_baud_t baud
);

-#define rtems_termios_interrupt_lock_acquire(tty, level) \
- rtems_interrupt_lock_acquire(&tty->interrupt_lock, level)
-
-#define rtems_termios_interrupt_lock_release(tty, level) \
- rtems_interrupt_lock_release(&tty->interrupt_lock, level)
-
#ifdef __cplusplus
}
#endif
diff --git a/cpukit/libcsupport/src/termios.c b/cpukit/libcsupport/src/termios.c
index 6119b22..f0ecad0 100644
--- a/cpukit/libcsupport/src/termios.c
+++ b/cpukit/libcsupport/src/termios.c
@@ -134,7 +134,7 @@ rtems_status_code rtems_termios_device_install(
rtems_device_minor_number minor,
const rtems_termios_device_handler *handler,
const rtems_termios_device_flow *flow,
- void *context
+ rtems_termios_device_context *context
)
{
rtems_status_code sc;
@@ -227,12 +227,23 @@ rtems_status_code rtems_termios_device_remove(
return RTEMS_SUCCESSFUL;
}

+static rtems_termios_tty *
+legacyContextToTTY (rtems_termios_device_context *ctx)
+{
+ return RTEMS_CONTAINER_OF (ctx, rtems_termios_tty, legacy_device_context);
+}
+
static bool
rtems_termios_callback_firstOpen(
rtems_termios_tty *tty,
+ rtems_termios_device_context *ctx,
+ struct termios *term,
rtems_libio_open_close_args_t *args
)
{
+ (void) ctx;
+ (void) term;
+
(*tty->device.firstOpen) (tty->major, tty->minor, args);

return true;
@@ -241,48 +252,61 @@ rtems_termios_callback_firstOpen(
static void
rtems_termios_callback_lastClose(
rtems_termios_tty *tty,
+ rtems_termios_device_context *ctx,
rtems_libio_open_close_args_t *args
)
{
+ (void) ctx;
+
(*tty->device.lastClose) (tty->major, tty->minor, args);
}

static int
-rtems_termios_callback_pollRead (struct rtems_termios_tty *tty)
+rtems_termios_callback_pollRead (rtems_termios_device_context *ctx)
{
+ rtems_termios_tty *tty = legacyContextToTTY (ctx);
+
return (*tty->device.pollRead) (tty->minor);
}

static void
rtems_termios_callback_write(
- rtems_termios_tty *tty,
- const char *buf,
- size_t len
+ rtems_termios_device_context *ctx,
+ const char *buf,
+ size_t len
)
{
+ rtems_termios_tty *tty = legacyContextToTTY (ctx);
+
(*tty->device.write) (tty->minor, buf, len);
}

static bool
rtems_termios_callback_setAttributes(
- rtems_termios_tty *tty,
- const struct termios *term
+ rtems_termios_device_context *ctx,
+ const struct termios *term
)
{
+ rtems_termios_tty *tty = legacyContextToTTY (ctx);
+
(*tty->device.setAttributes) (tty->minor, term);

return true;
}

static void
-rtems_termios_callback_stopRemoteTx (rtems_termios_tty *tty)
+rtems_termios_callback_stopRemoteTx (rtems_termios_device_context *ctx)
{
+ rtems_termios_tty *tty = legacyContextToTTY (ctx);
+
(*tty->device.stopRemoteTx) (tty->minor);
}

static void
-rtems_termios_callback_startRemoteTx (rtems_termios_tty *tty)
+rtems_termios_callback_startRemoteTx (rtems_termios_device_context *ctx)
{
+ rtems_termios_tty *tty = legacyContextToTTY (ctx);
+
(*tty->device.startRemoteTx) (tty->minor);
}

@@ -292,21 +316,22 @@ rtems_termios_callback_startRemoteTx (rtems_termios_tty *tty)
static void
drainOutput (struct rtems_termios_tty *tty)
{
+ rtems_termios_device_context *ctx = tty->device_context;
rtems_interrupt_lock_context lock_context;
rtems_status_code sc;

if (tty->handler.mode != TERMIOS_POLLED) {
- rtems_termios_interrupt_lock_acquire (tty, &lock_context);
+ rtems_termios_device_lock_acquire (ctx, &lock_context);
while (tty->rawOutBuf.Tail != tty->rawOutBuf.Head) {
tty->rawOutBufState = rob_wait;
- rtems_termios_interrupt_lock_release (tty, &lock_context);
+ rtems_termios_device_lock_release (ctx, &lock_context);
sc = rtems_semaphore_obtain(
tty->rawOutBuf.Semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
if (sc != RTEMS_SUCCESSFUL)
rtems_fatal_error_occurred (sc);
- rtems_termios_interrupt_lock_acquire (tty, &lock_context);
+ rtems_termios_device_lock_acquire (ctx, &lock_context);
}
- rtems_termios_interrupt_lock_release (tty, &lock_context);
+ rtems_termios_device_lock_release (ctx, &lock_context);
}
}

@@ -344,7 +369,7 @@ rtems_termios_destroy_tty (rtems_termios_tty *tty, void *arg, bool last_close)
rtems_fatal_error_occurred (sc);
}
if (last_close && tty->handler.last_close)
- (*tty->handler.last_close)(tty, arg);
+ (*tty->handler.last_close)(tty, tty->device_context, arg);

if (tty->device_node != NULL)
tty->device_node->tty = NULL;
@@ -355,7 +380,10 @@ rtems_termios_destroy_tty (rtems_termios_tty *tty, void *arg, bool last_close)
if ((tty->handler.poll_read == NULL) ||
(tty->handler.mode == TERMIOS_TASK_DRIVEN))
rtems_semaphore_delete (tty->rawInBuf.Semaphore);
- rtems_interrupt_lock_destroy (&tty->interrupt_lock);
+
+ if (tty->device_context == &tty->legacy_device_context)
+ rtems_interrupt_lock_destroy (&tty->legacy_device_context.interrupt_lock);
+
free (tty->rawInBuf.theBuf);
free (tty->rawOutBuf.theBuf);
free (tty->cbuf);
@@ -489,7 +517,10 @@ rtems_termios_open_tty(
tty->device = *callbacks;
}

- rtems_interrupt_lock_initialize (&tty->interrupt_lock, "Termios");
+ if (tty->device_context == NULL) {
+ tty->device_context = &tty->legacy_device_context;
+ rtems_termios_device_context_initialize (tty->device_context, "Termios");
+ }

/*
* Create I/O tasks
@@ -569,8 +600,8 @@ rtems_termios_open_tty(
}
args->iop->data1 = tty;
if (!tty->refcount++) {
- if (tty->handler.first_open &&
- !(*tty->handler.first_open)(tty, args)) {
+ if (tty->handler.first_open && !(*tty->handler.first_open)(
+ tty, tty->device_context, &tty->termios, args)) {
rtems_termios_destroy_tty(tty, args, false);
return NULL;
}
@@ -683,24 +714,26 @@ rtems_termios_open (
static void
flushOutput (struct rtems_termios_tty *tty)
{
+ rtems_termios_device_context *ctx = tty->device_context;
rtems_interrupt_lock_context lock_context;

- rtems_termios_interrupt_lock_acquire (tty, &lock_context);
+ rtems_termios_device_lock_acquire (ctx, &lock_context);
tty->rawOutBuf.Tail = 0;
tty->rawOutBuf.Head = 0;
tty->rawOutBufState = rob_idle;
- rtems_termios_interrupt_lock_release (tty, &lock_context);
+ rtems_termios_device_lock_release (ctx, &lock_context);
}

static void
flushInput (struct rtems_termios_tty *tty)
{
+ rtems_termios_device_context *ctx = tty->device_context;
rtems_interrupt_lock_context lock_context;

- rtems_termios_interrupt_lock_acquire (tty, &lock_context);
+ rtems_termios_device_lock_acquire (ctx, &lock_context);
tty->rawInBuf.Tail = 0;
tty->rawInBuf.Head = 0;
- rtems_termios_interrupt_lock_release (tty, &lock_context);
+ rtems_termios_device_lock_release (ctx, &lock_context);
}

static void
@@ -784,6 +817,7 @@ rtems_status_code rtems_termios_bufsize (
static void
termios_set_flowctrl(struct rtems_termios_tty *tty)
{
+ rtems_termios_device_context *ctx = tty->device_context;
rtems_interrupt_lock_context lock_context;
/*
* check for flow control options to be switched off
@@ -798,16 +832,16 @@ termios_set_flowctrl(struct rtems_termios_tty *tty)
/* has output been stopped due to received XOFF? */
if (tty->flow_ctrl & FL_OSTOP) {
/* disable interrupts */
- rtems_termios_interrupt_lock_acquire (tty, &lock_context);
+ rtems_termios_device_lock_acquire (ctx, &lock_context);
tty->flow_ctrl &= ~FL_OSTOP;
/* check for chars in output buffer (or rob_state?) */
if (tty->rawOutBufState != rob_idle) {
/* if chars available, call write function... */
(*tty->handler.write)(
- tty, &tty->rawOutBuf.theBuf[tty->rawOutBuf.Tail],1);
+ ctx, &tty->rawOutBuf.theBuf[tty->rawOutBuf.Tail],1);
}
/* reenable interrupts */
- rtems_termios_interrupt_lock_release (tty, &lock_context);
+ rtems_termios_device_lock_release (ctx, &lock_context);
}
}
/* check for incoming XON/XOFF flow control switched off */
@@ -826,7 +860,7 @@ termios_set_flowctrl(struct rtems_termios_tty *tty)
/* restart remote Tx, if it was stopped */
if ((tty->flow_ctrl & FL_IRTSOFF) &&
(tty->flow.start_remote_tx != NULL)) {
- tty->flow.start_remote_tx(tty);
+ tty->flow.start_remote_tx(ctx);
}
tty->flow_ctrl &= ~(FL_IRTSOFF);
}
@@ -906,7 +940,7 @@ rtems_termios_ioctl (void *arg)
}
}
if (tty->handler.set_attributes) {
- sc = (*tty->handler.set_attributes)(tty, &tty->termios) ?
+ sc = (*tty->handler.set_attributes)(tty->device_context, &tty->termios) ?
RTEMS_SUCCESSFUL : RTEMS_IO_ERROR;
}
break;
@@ -1003,7 +1037,7 @@ startXmit (
nToSend = 0;
/* stop transmitter */
if (transmitting) {
- (*tty->handler.write) (tty, NULL, 0);
+ (*tty->handler.write) (tty->device_context, NULL, 0);
}
} else {
/* when flow control XON or XOF, don't send blocks of data */
@@ -1017,7 +1051,7 @@ startXmit (
nToSend = tty->rawOutBuf.Head - newTail;

(*tty->handler.write)(
- tty, &tty->rawOutBuf.theBuf[newTail], nToSend);
+ tty->device_context, &tty->rawOutBuf.theBuf[newTail], nToSend);
}

return nToSend;
@@ -1032,11 +1066,12 @@ rtems_termios_puts (
{
const char *buf = _buf;
unsigned int newHead;
+ rtems_termios_device_context *ctx = tty->device_context;
rtems_interrupt_lock_context lock_context;
rtems_status_code sc;

if (tty->handler.mode == TERMIOS_POLLED) {
- (*tty->handler.write)(tty, buf, len);
+ (*tty->handler.write)(ctx, buf, len);
return;
}

@@ -1049,15 +1084,15 @@ rtems_termios_puts (
if (newHead >= tty->rawOutBuf.Size)
newHead -= tty->rawOutBuf.Size;

- rtems_termios_interrupt_lock_acquire (tty, &lock_context);
+ rtems_termios_device_lock_acquire (ctx, &lock_context);
while (newHead == tty->rawOutBuf.Tail) {
tty->rawOutBufState = rob_wait;
- rtems_termios_interrupt_lock_release (tty, &lock_context);
+ rtems_termios_device_lock_release (ctx, &lock_context);
sc = rtems_semaphore_obtain(
tty->rawOutBuf.Semaphore, RTEMS_WAIT, RTEMS_NO_TIMEOUT);
if (sc != RTEMS_SUCCESSFUL)
rtems_fatal_error_occurred (sc);
- rtems_termios_interrupt_lock_acquire (tty, &lock_context);
+ rtems_termios_device_lock_acquire (ctx, &lock_context);
}

/* Determine free space up to current tail or end of ring buffer */
@@ -1090,7 +1125,7 @@ rtems_termios_puts (
startXmit (tty, tty->rawOutBuf.Tail, false);
}

- rtems_termios_interrupt_lock_release (tty, &lock_context);
+ rtems_termios_device_lock_release (ctx, &lock_context);

buf += nToCopy;
len -= nToCopy;
@@ -1371,7 +1406,7 @@ fillBufferPoll (struct rtems_termios_tty *tty)

if (tty->termios.c_lflag & ICANON) {
for (;;) {
- n = (*tty->handler.poll_read)(tty);
+ n = (*tty->handler.poll_read)(tty->device_context);
if (n < 0) {
rtems_task_wake_after (1);
} else {
@@ -1384,7 +1419,7 @@ fillBufferPoll (struct rtems_termios_tty *tty)

then = rtems_clock_get_ticks_since_boot();
for (;;) {
- n = (*tty->handler.poll_read)(tty);
+ n = (*tty->handler.poll_read)(tty->device_context);
if (n < 0) {
if (tty->termios.c_cc[VMIN]) {
if (tty->termios.c_cc[VTIME] && tty->ccount) {
@@ -1447,12 +1482,12 @@ fillBufferQueue (struct rtems_termios_tty *tty)
|| (tty->flow_ctrl & FL_OSTOP))) {
/* XON should be sent now... */
(*tty->handler.write)(
- tty, (void *)&(tty->termios.c_cc[VSTART]), 1);
+ tty->device_context, (void *)&(tty->termios.c_cc[VSTART]), 1);
} else if (tty->flow_ctrl & FL_MDRTS) {
tty->flow_ctrl &= ~FL_IRTSOFF;
/* activate RTS line */
if (tty->flow.start_remote_tx != NULL) {
- tty->flow.start_remote_tx(tty);
+ tty->flow.start_remote_tx(tty->device_context);
}
}
}
@@ -1550,6 +1585,7 @@ rtems_termios_enqueue_raw_characters (void *ttyp, const char *buf, int len)
char c;
int dropped = 0;
bool flow_rcv = false; /* true, if flow control char received */
+ rtems_termios_device_context *ctx = tty->device_context;
rtems_interrupt_lock_context lock_context;

if (rtems_termios_linesw[tty->t_line].l_rint != NULL) {
@@ -1598,21 +1634,21 @@ rtems_termios_enqueue_raw_characters (void *ttyp, const char *buf, int len)
/* restart output according to FL_ORCVXOF flag */
if ((tty->flow_ctrl & (FL_ORCVXOF | FL_OSTOP)) == FL_OSTOP) {
/* disable interrupts */
- rtems_termios_interrupt_lock_acquire (tty, &lock_context);
+ rtems_termios_device_lock_acquire (ctx, &lock_context);
tty->flow_ctrl &= ~FL_OSTOP;
/* check for chars in output buffer (or rob_state?) */
if (tty->rawOutBufState != rob_idle) {
/* if chars available, call write function... */
(*tty->handler.write)(
- tty, &tty->rawOutBuf.theBuf[tty->rawOutBuf.Tail], 1);
+ ctx, &tty->rawOutBuf.theBuf[tty->rawOutBuf.Tail], 1);
}
/* reenable interrupts */
- rtems_termios_interrupt_lock_release (tty, &lock_context);
+ rtems_termios_device_lock_release (ctx, &lock_context);
}
} else {
newTail = (tty->rawInBuf.Tail + 1) % tty->rawInBuf.Size;
/* if chars_in_buffer > highwater */
- rtems_termios_interrupt_lock_acquire (tty, &lock_context);
+ rtems_termios_device_lock_acquire (ctx, &lock_context);
if ((((newTail - tty->rawInBuf.Head + tty->rawInBuf.Size)
% tty->rawInBuf.Size) > tty->highwater) &&
!(tty->flow_ctrl & FL_IREQXOF)) {
@@ -1625,20 +1661,20 @@ rtems_termios_enqueue_raw_characters (void *ttyp, const char *buf, int len)
/* if tx is stopped due to XOFF or out of data */
/* call write function here */
tty->flow_ctrl |= FL_ISNTXOF;
- (*tty->handler.write)(tty,
+ (*tty->handler.write)(ctx,
(void *)&(tty->termios.c_cc[VSTOP]), 1);
}
} else if ((tty->flow_ctrl & (FL_MDRTS | FL_IRTSOFF)) == (FL_MDRTS) ) {
tty->flow_ctrl |= FL_IRTSOFF;
/* deactivate RTS line */
if (tty->flow.stop_remote_tx != NULL) {
- tty->flow.stop_remote_tx(tty);
+ tty->flow.stop_remote_tx(ctx);
}
}
}

/* reenable interrupts */
- rtems_termios_interrupt_lock_release (tty, &lock_context);
+ rtems_termios_device_lock_release (ctx, &lock_context);

if (newTail == tty->rawInBuf.Head) {
dropped++;
@@ -1672,16 +1708,17 @@ rtems_termios_refill_transmitter (struct rtems_termios_tty *tty)
bool wakeUpWriterTask = false;
unsigned int newTail;
int nToSend;
+ rtems_termios_device_context *ctx = tty->device_context;
rtems_interrupt_lock_context lock_context;
int len;

- rtems_termios_interrupt_lock_acquire (tty, &lock_context);
+ rtems_termios_device_lock_acquire (ctx, &lock_context);

/* check for XOF/XON to send */
if ((tty->flow_ctrl & (FL_MDXOF | FL_IREQXOF | FL_ISNTXOF))
== (FL_MDXOF | FL_IREQXOF)) {
/* XOFF should be sent now... */
- (*tty->handler.write)(tty, (void *)&(tty->termios.c_cc[VSTOP]), 1);
+ (*tty->handler.write)(ctx, (void *)&(tty->termios.c_cc[VSTOP]), 1);

tty->t_dqlen--;
tty->flow_ctrl |= FL_ISNTXOF;
@@ -1697,7 +1734,7 @@ rtems_termios_refill_transmitter (struct rtems_termios_tty *tty)
* buffer, although the corresponding data is not yet out!
* Therefore the dequeue "length" should be reduced by 1
*/
- (*tty->handler.write)(tty, (void *)&(tty->termios.c_cc[VSTART]), 1);
+ (*tty->handler.write)(ctx, (void *)&(tty->termios.c_cc[VSTART]), 1);

tty->t_dqlen--;
tty->flow_ctrl &= ~FL_ISNTXOF;
@@ -1714,7 +1751,7 @@ rtems_termios_refill_transmitter (struct rtems_termios_tty *tty)
wakeUpWriterTask = true;
}

- (*tty->handler.write) (tty, NULL, 0);
+ (*tty->handler.write) (ctx, NULL, 0);
nToSend = 0;
} else {
len = tty->t_dqlen;
@@ -1734,7 +1771,7 @@ rtems_termios_refill_transmitter (struct rtems_termios_tty *tty)
* Buffer has become empty
*/
tty->rawOutBufState = rob_idle;
- (*tty->handler.write) (tty, NULL, 0);
+ (*tty->handler.write) (ctx, NULL, 0);
nToSend = 0;

/*
@@ -1751,7 +1788,7 @@ rtems_termios_refill_transmitter (struct rtems_termios_tty *tty)
}
}

- rtems_termios_interrupt_lock_release (tty, &lock_context);
+ rtems_termios_device_lock_release (ctx, &lock_context);

if (wakeUpWriterTask) {
rtems_semaphore_release (tty->rawOutBuf.Semaphore);
@@ -1854,6 +1891,7 @@ static rtems_task rtems_termios_txdaemon(rtems_task_argument argument)
static rtems_task rtems_termios_rxdaemon(rtems_task_argument argument)
{
struct rtems_termios_tty *tty = (struct rtems_termios_tty *)argument;
+ rtems_termios_device_context *ctx = tty->device_context;
rtems_event_set the_event;
int c;
char c_buf;
@@ -1876,7 +1914,7 @@ static rtems_task rtems_termios_rxdaemon(rtems_task_argument argument)
/*
* do something
*/
- c = tty->handler.poll_read(tty);
+ c = tty->handler.poll_read(ctx);
if (c != EOF) {
/*
* poll_read did call enqueue on its own
diff --git a/cpukit/libcsupport/src/termios_setbestbaud.c b/cpukit/libcsupport/src/termios_setbestbaud.c
index 3d7a3a8..7680118 100644
--- a/cpukit/libcsupport/src/termios_setbestbaud.c
+++ b/cpukit/libcsupport/src/termios_setbestbaud.c
@@ -19,8 +19,8 @@
#include <rtems/termiostypes.h>

void rtems_termios_set_best_baud(
- rtems_termios_tty *tty,
- uint32_t baud
+ struct termios *term,
+ uint32_t baud
)
{
const rtems_assoc_t *current = &rtems_termios_baud_table[ 0 ];
@@ -41,5 +41,5 @@ void rtems_termios_set_best_baud(
cbaud = B460800;
}

- tty->termios.c_cflag = (tty->termios.c_cflag & ~cbaud_mask) | cbaud;
+ term->c_cflag = (term->c_cflag & ~cbaud_mask) | cbaud;
}
diff --git a/cpukit/libnetworking/net/if_ppp.c b/cpukit/libnetworking/net/if_ppp.c
index a1d7a62..95fa556 100644
--- a/cpukit/libnetworking/net/if_ppp.c
+++ b/cpukit/libnetworking/net/if_ppp.c
@@ -387,7 +387,7 @@ static rtems_task ppp_txdaemon(rtems_task_argument arg)

/* write out frame byte to start the transmission */
sc->sc_outchar = (u_char)PPP_FLAG;
- (*tp->handler.write)(tp, (char *)&sc->sc_outchar, 1);
+ (*tp->handler.write)(tp->device_context, (char *)&sc->sc_outchar, 1);
}

/* check to see if we need to free some empty mbufs */
diff --git a/cpukit/libnetworking/net/ppp_tty.c b/cpukit/libnetworking/net/ppp_tty.c
index 613d9c5..85a336c 100644
--- a/cpukit/libnetworking/net/ppp_tty.c
+++ b/cpukit/libnetworking/net/ppp_tty.c
@@ -568,6 +568,7 @@ pppstart(struct rtems_termios_tty *tp)
u_long ioffset = (u_long )0;
struct mbuf *m = (struct mbuf *)0;
struct ppp_softc *sc = tp->t_sc;
+ rtems_termios_device_context *ctx = rtems_termios_get_device_context(tp);

/* ensure input is valid and we are busy */
if (( sc != NULL ) && ( sc->sc_outflag & SC_TX_BUSY )) {
@@ -606,7 +607,7 @@ pppstart(struct rtems_termios_tty *tp)
sc->sc_outflag |= SC_TX_LASTCHAR;
sc->sc_outflag &=~(SC_TX_FCS);
sc->sc_outchar = (u_char)PPP_FLAG;
- (*tp->handler.write)(tp, (char *)&sc->sc_outchar, 1);
+ (*tp->handler.write)(ctx, (char *)&sc->sc_outchar, 1);
return(0);
}
}
@@ -643,7 +644,7 @@ pppstart(struct rtems_termios_tty *tp)
}

/* write out the character(s) and update the stats */
- (*tp->handler.write)(tp, (char *)sendBegin, (ioffset > 0) ? ioffset : 1);
+ (*tp->handler.write)(ctx, (char *)sendBegin, (ioffset > 0) ? ioffset : 1);
sc->sc_stats.ppp_obytes += (ioffset > 0) ? ioffset : 1;
sc->sc_outoff += ioffset;
}
diff --git a/doc/bsp_howto/console.t b/doc/bsp_howto/console.t
index a165f72..687ecda 100644
--- a/doc/bsp_howto/console.t
+++ b/doc/bsp_howto/console.t
@@ -274,6 +274,7 @@ initialization example the device name is also present. Her is an example heade

/* Low-level driver specific data structure */
typedef struct @{
+ rtems_termios_device_context base;
const char *device_name;
volatile module_register_block *regs;
/* More stuff */
@@ -298,12 +299,12 @@ characters from @code{buf} to the serial device specified by @code{tty}.
@example
@group
static void my_driver_poll_write(
- rtems_termios_tty *tty,
- const char *buf,
- size_t n
+ rtems_termios_device_context *base,
+ const char *buf,
+ size_t n
)
@{
- my_driver_context *ctx = rtems_termios_get_device_context(tty);
+ my_driver_context *ctx = (my_driver_context *) base;
size_t i;

/* Write */
@@ -320,9 +321,9 @@ available, then the routine should return minus one.

@example
@group
-static int my_driver_poll_read(rtems_termios_tty *tty)
+static int my_driver_poll_read(rtems_termios_device_context *base)
@{
- my_driver_context *ctx = rtems_termios_get_device_context(tty);
+ my_driver_context *ctx = (my_driver_context *) base;

/* Check if a character is available */
if (my_driver_can_read_char(ctx)) @{
@@ -409,12 +410,12 @@ character.
@example
@group
static void my_driver_interrupt_write(
- rtems_termios_tty *tty,
- const char *buf,
- size_t n
+ rtems_termios_device_context *base,
+ const char *buf,
+ size_t n
)
@{
- my_driver_context *ctx = rtems_termios_get_device_context(tty);
+ my_driver_context *ctx = (my_driver_context *) base;

/*
* Tell the device to transmit some characters from buf (less than
@@ -518,10 +519,12 @@ During the first open of the device Termios will call the
@group
static bool my_driver_first_open(
rtems_termios_tty *tty,
+ rtems_termios_device_context *base,
+ struct termios *term,
rtems_libio_open_close_args_t *args
)
@{
- my_driver_context *ctx = rtems_termios_get_device_context(tty);
+ my_driver_context *ctx = (my_driver_context *) base;
rtems_status_code sc;
bool ok;

@@ -542,13 +545,13 @@ static bool my_driver_first_open(
/*
* Alternatively you can set the best baud.
*/
- rtems_termios_set_best_baud(tty, MY_DRIVER_BAUD_RATE);
+ rtems_termios_set_best_baud(term, MY_DRIVER_BAUD_RATE);

/*
* To propagate the initial Termios attributes to the device use
* this.
*/
- ok = my_driver_set_attributes(tty, rtems_termios_get_termios(tty));
+ ok = my_driver_set_attributes(base, term);
if (!ok) @{
/* This is bad */
@}
@@ -574,10 +577,11 @@ happens on the device.
@group
static void my_driver_last_close(
rtems_termios_tty *tty,
+ rtems_termios_device_context *base,
rtems_libio_open_close_args_t *args
)
@{
- my_driver_context *ctx = rtems_termios_get_device_context(tty);
+ my_driver_context *ctx = (my_driver_context *) base;

/*
* The driver may do some cleanup here.
@@ -618,11 +622,11 @@ handler.
@example
@group
static bool my_driver_set_attributes(
- rtems_termios_tty *tty,
- const struct termios *term
+ rtems_termios_device_context *base,
+ const struct termios *term
)
@{
- my_driver_context *ctx = rtems_termios_get_device_context(tty);
+ my_driver_context *ctx = (my_driver_context *) base;

/*
* Inspect the termios data structure and configure the device
diff --git a/testsuites/libtests/termios01/init.c b/testsuites/libtests/termios01/init.c
index 080363f..c836b3d 100644
--- a/testsuites/libtests/termios01/init.c
+++ b/testsuites/libtests/termios01/init.c
@@ -517,6 +517,11 @@ static void test_termios_cfmakeraw(void)
rtems_test_assert( term.c_cflag & CS8 );
}

+typedef struct {
+ rtems_termios_device_context base;
+ bool done;
+} device_context;
+
static rtems_status_code test_early_device_install_remove(
rtems_device_major_number major,
rtems_device_minor_number minor,
@@ -528,7 +533,7 @@ static rtems_status_code test_early_device_install_remove(

rtems_resource_snapshot_take( &snapshot );

- sc = rtems_termios_device_install( "/", 0, 0, NULL, NULL );
+ sc = rtems_termios_device_install( "/", 0, 0, NULL, NULL, NULL );
rtems_test_assert( sc == RTEMS_INCORRECT_STATE );

sc = rtems_termios_device_remove( "/", 0, 0 );
@@ -630,14 +635,18 @@ static void test_device_install_remove(void)

static bool first_open_error(
rtems_termios_tty *tty,
+ rtems_termios_device_context *base,
+ struct termios *term,
rtems_libio_open_close_args_t *args
)
{
- bool *done = rtems_termios_get_device_context( tty );
+ device_context *ctx = (device_context *) base;

+ (void) tty;
+ (void) term;
(void) args;

- *done = true;
+ ctx->done = true;

return false;
}
@@ -655,7 +664,10 @@ static void test_first_open_error(void)
rtems_status_code sc;
rtems_libio_t iop;
rtems_libio_open_close_args_t args;
- bool done = false;
+ device_context ctx = {
+ .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER( "abc" ),
+ .done = false
+ };

rtems_resource_snapshot_take( &snapshot );

@@ -665,7 +677,7 @@ static void test_first_open_error(void)
minor,
&handler,
NULL,
- &done
+ &ctx.base
);
rtems_test_assert( sc == RTEMS_SUCCESSFUL );

@@ -673,10 +685,10 @@ static void test_first_open_error(void)
memset( &args, 0, sizeof( args ) );
args.iop = &iop;

- rtems_test_assert( !done );
+ rtems_test_assert( !ctx.done );
sc = rtems_termios_device_open( major, minor, &args );
rtems_test_assert( sc == RTEMS_NO_MEMORY );
- rtems_test_assert( done );
+ rtems_test_assert( ctx.done );

sc = rtems_termios_device_remove( &dev[0], major, minor );
rtems_test_assert( sc == RTEMS_SUCCESSFUL );
@@ -685,15 +697,15 @@ static void test_first_open_error(void)
}

static bool set_attributes_error(
- rtems_termios_tty *tty,
+ rtems_termios_device_context *base,
const struct termios *term
)
{
- bool *done = rtems_termios_get_device_context( tty );
+ device_context *ctx = (device_context *) base;

(void) term;

- *done = true;
+ ctx->done = true;

return false;
}
@@ -713,7 +725,10 @@ static void test_set_attributes_error(void)
rtems_libio_open_close_args_t oc_args;
rtems_libio_ioctl_args_t io_args;
struct termios term;
- bool done = false;
+ device_context ctx = {
+ .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER( "abc" ),
+ .done = false
+ };

rtems_resource_snapshot_take( &snapshot );

@@ -723,7 +738,7 @@ static void test_set_attributes_error(void)
minor,
&handler,
NULL,
- &done
+ &ctx.base
);
rtems_test_assert( sc == RTEMS_SUCCESSFUL );

@@ -739,10 +754,10 @@ static void test_set_attributes_error(void)
io_args.command = RTEMS_IO_SET_ATTRIBUTES;
io_args.buffer = &term;

- rtems_test_assert( !done );
+ rtems_test_assert( !ctx.done );
sc = rtems_termios_ioctl( &io_args );
rtems_test_assert( sc == RTEMS_IO_ERROR );
- rtems_test_assert( done );
+ rtems_test_assert( ctx.done );

sc = rtems_termios_device_close( &oc_args );
rtems_test_assert( sc == RTEMS_SUCCESSFUL );
@@ -790,15 +805,14 @@ static void test_set_best_baud(void)
size_t i;

for ( i = 0; i < n; ++i ) {
- rtems_termios_tty tty;
- struct termios *term = rtems_termios_get_termios( &tty );
+ struct termios term;
tcflag_t cbaud_mask = CBAUD;

- memset( &tty, 0xff, sizeof( tty ) );
- rtems_termios_set_best_baud( &tty, baud_to_cflag_table[ i ].baud );
+ memset( &term, 0xff, sizeof( term ) );
+ rtems_termios_set_best_baud( &term, baud_to_cflag_table[ i ].baud );

rtems_test_assert(
- (term->c_cflag & cbaud_mask) == baud_to_cflag_table[ i ].cflag
+ (term.c_cflag & cbaud_mask) == baud_to_cflag_table[ i ].cflag
);
}
}
--
1.8.4.5
Sebastian Huber
2014-10-07 14:36:27 UTC
Permalink
Add a simple Termios console driver using a table for statically
registered devices used in console_initialize() and dynamic installation
via console_device_install().
---
c/src/lib/libbsp/Makefile.am | 1 +
c/src/lib/libbsp/preinstall.am | 4 +
c/src/lib/libbsp/shared/console-termios-init.c | 101 ++++++++++++++++
c/src/lib/libbsp/shared/include/console-termios.h | 136 ++++++++++++++++++++++
c/src/lib/libbsp/shared/include/fatal.h | 2 +
5 files changed, 244 insertions(+)
create mode 100644 c/src/lib/libbsp/shared/console-termios-init.c
create mode 100644 c/src/lib/libbsp/shared/include/console-termios.h

diff --git a/c/src/lib/libbsp/Makefile.am b/c/src/lib/libbsp/Makefile.am
index e947192..ac64f37 100644
--- a/c/src/lib/libbsp/Makefile.am
+++ b/c/src/lib/libbsp/Makefile.am
@@ -34,6 +34,7 @@ include_bspdir = $(includedir)/bsp
include_bsp_HEADERS =
include_bsp_HEADERS += shared/include/default-initial-extension.h
include_bsp_HEADERS += shared/include/fatal.h
+include_bsp_HEADERS += shared/include/console-termios.h

include $(srcdir)/preinstall.am
include $(top_srcdir)/automake/subdirs.am
diff --git a/c/src/lib/libbsp/preinstall.am b/c/src/lib/libbsp/preinstall.am
index abaf028..651f136 100644
--- a/c/src/lib/libbsp/preinstall.am
+++ b/c/src/lib/libbsp/preinstall.am
@@ -26,3 +26,7 @@ $(PROJECT_INCLUDE)/bsp/fatal.h: shared/include/fatal.h $(PROJECT_INCLUDE)/bsp/$(
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/fatal.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/fatal.h

+$(PROJECT_INCLUDE)/bsp/console-termios.h: shared/include/console-termios.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/console-termios.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/console-termios.h
+
diff --git a/c/src/lib/libbsp/shared/console-termios-init.c b/c/src/lib/libbsp/shared/console-termios-init.c
new file mode 100644
index 0000000..08b0a7f
--- /dev/null
+++ b/c/src/lib/libbsp/shared/console-termios-init.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2014 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Dornierstr. 4
+ * 82178 Puchheim
+ * Germany
+ * <rtems-L1vi/***@public.gmane.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <bsp/console-termios.h>
+#include <bsp/fatal.h>
+
+#include <rtems/console.h>
+
+static rtems_interrupt_lock console_lock =
+ RTEMS_INTERRUPT_LOCK_INITIALIZER( "console" );
+
+static rtems_device_major_number console_major = UINT32_MAX;
+
+static rtems_device_minor_number console_minor;
+
+rtems_status_code console_device_install(
+ const char *device_file,
+ const rtems_termios_device_handler *handler,
+ const rtems_termios_device_flow *flow,
+ rtems_termios_device_context *context
+)
+{
+ rtems_interrupt_lock_context lock_context;
+ rtems_device_minor_number minor;
+
+ rtems_interrupt_lock_acquire( &console_lock, &lock_context );
+ minor = console_minor;
+ ++console_minor;
+ rtems_interrupt_lock_release( &console_lock, &lock_context );
+
+ return rtems_termios_device_install(
+ device_file,
+ console_major,
+ minor,
+ handler,
+ flow,
+ context
+ );
+}
+
+bool console_device_probe_default(rtems_termios_device_context *context)
+{
+ (void) context;
+
+ return true;
+}
+
+rtems_device_driver console_initialize(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg
+)
+{
+ bool console_device_done = false;
+
+ rtems_termios_initialize();
+
+ for ( minor = 0; minor < console_device_count; ++minor ) {
+ const console_device *ctx = &console_device_table[ minor ];
+ rtems_status_code sc;
+
+ if ( ( *ctx->probe )( ctx->context ) ) {
+ sc = rtems_termios_device_install(
+ ctx->device_file,
+ major,
+ minor,
+ ctx->handler,
+ ctx->flow,
+ ctx->context
+ );
+ if ( sc != RTEMS_SUCCESSFUL ) {
+ bsp_fatal( BSP_FATAL_CONSOLE_INSTALL_0 );
+ }
+
+ if ( !console_device_done ) {
+ console_device_done = true;
+
+ sc = rtems_io_register_name( CONSOLE_DEVICE_NAME, major, minor );
+ if ( sc != RTEMS_SUCCESSFUL ) {
+ bsp_fatal( BSP_FATAL_CONSOLE_INSTALL_1 );
+ }
+ }
+ }
+ }
+
+ console_major = major;
+ console_minor = minor;
+
+ return RTEMS_SUCCESSFUL;
+}
diff --git a/c/src/lib/libbsp/shared/include/console-termios.h b/c/src/lib/libbsp/shared/include/console-termios.h
new file mode 100644
index 0000000..bbb9f35
--- /dev/null
+++ b/c/src/lib/libbsp/shared/include/console-termios.h
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 2014 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Dornierstr. 4
+ * 82178 Puchheim
+ * Germany
+ * <rtems-L1vi/***@public.gmane.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#ifndef BSP_CONSOLE_TERMIOS_H
+#define BSP_CONSOLE_TERMIOS_H
+
+#include <rtems/termiostypes.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup ConsoleTermios Termios Console Driver
+ *
+ * @ingroup TermiostypesSupport
+ *
+ * @brief Console driver for Termios devices.
+ *
+ * In order to use this driver add the following lines to the Makefile.am of
+ * the BSP:
+ *
+ * @code
+ * libbsp_a_SOURCES += ../../shared/console-termios-init.c
+ * libbsp_a_SOURCES += ../../shared/console-termios.c
+ * libbsp_a_SOURCES += console/console-config.c
+ * @endcode
+ *
+ * Define the console_device_table and console_device_count in the
+ * console-config.c file of the BSP.
+ *
+ * @{
+ */
+
+/**
+ * @brief Console device probe function type.
+ *
+ * @param[in] context The Termios device context.
+ *
+ * @retval true Install this device.
+ * @retval false Otherwise.
+ */
+typedef bool (*console_device_probe)(rtems_termios_device_context *context);
+
+/**
+ * @brief Console device information.
+ */
+typedef struct {
+ /**
+ * @brief The device file path.
+ *
+ * The "/dev/console" device will be automatically installed as the first
+ * device of console_device_table with a successful probe.
+ */
+ const char *device_file;
+
+ /**
+ * @brief The device probe function.
+ */
+ console_device_probe probe;
+
+ /**
+ * @brief The Termios device handler.
+ */
+ const rtems_termios_device_handler *handler;
+
+ /**
+ * @brief The Termios device flow control handler.
+ */
+ const rtems_termios_device_flow *flow;
+
+ /**
+ * @brief The Termios device context.
+ */
+ rtems_termios_device_context *context;
+} console_device;
+
+/**
+ * @brief Installs a console device after console driver initialization.
+ *
+ * @param[in] device_file The device file path.
+ * @param[in] handler The Termios device handler. It must be persistent
+ * throughout the installed time of the device.
+ * @param[in] flow The Termios device flow control handler. The device flow
+ * control handler are optional and may be @c NULL. If present must be
+ * persistent throughout the installed time of the device.
+ * @param[in] context The Termios device context. It must be persistent
+ * throughout the installed time of the device.
+ */
+rtems_status_code console_device_install(
+ const char *device_file,
+ const rtems_termios_device_handler *handler,
+ const rtems_termios_device_flow *flow,
+ rtems_termios_device_context *context
+);
+
+/**
+ * @brief Returns true and does nothing else.
+ */
+bool console_device_probe_default(rtems_termios_device_context *context);
+
+/**
+ * @brief Table for console devices installed via console_initialize() during
+ * system initialization.
+ *
+ * It must be provided by the BSP.
+ *
+ * @see console_device_count.
+ */
+extern const console_device console_device_table[];
+
+/**
+ * @brief Count of entries in the console_device_table.
+ *
+ * It must be provided by the BSP.
+ */
+extern const size_t console_device_count;
+
+/** @{ */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* BSP_CONSOLE_TERMIOS_H */
diff --git a/c/src/lib/libbsp/shared/include/fatal.h b/c/src/lib/libbsp/shared/include/fatal.h
index e928bba..b57fbaa 100644
--- a/c/src/lib/libbsp/shared/include/fatal.h
+++ b/c/src/lib/libbsp/shared/include/fatal.h
@@ -38,6 +38,8 @@ typedef enum {
BSP_FATAL_CONSOLE_REGISTER_DEV_0,
BSP_FATAL_CONSOLE_REGISTER_DEV_1,
BSP_FATAL_CONSOLE_NO_DEV,
+ BSP_FATAL_CONSOLE_INSTALL_0,
+ BSP_FATAL_CONSOLE_INSTALL_1,

/* ARM fatal codes */
BSP_ARM_A9MPCORE_FATAL_CLOCK_IRQ_INSTALL = BSP_FATAL_CODE_BLOCK(1),
--
1.8.4.5
Sebastian Huber
2014-10-07 14:36:31 UTC
Permalink
---
cpukit/libnetworking/net/ppp_tty.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/cpukit/libnetworking/net/ppp_tty.c b/cpukit/libnetworking/net/ppp_tty.c
index 85a336c..1051048 100644
--- a/cpukit/libnetworking/net/ppp_tty.c
+++ b/cpukit/libnetworking/net/ppp_tty.c
@@ -577,6 +577,10 @@ pppstart(struct rtems_termios_tty *tp)
/* Ready with PPP_FLAG Character ? */
if(sc->sc_outflag & SC_TX_LASTCHAR){
sc->sc_outflag &= ~(SC_TX_BUSY | SC_TX_FCS | SC_TX_LASTCHAR);
+
+ /* Notify driver that we have nothing to transmit */
+ (*tp->handler.write)(ctx, NULL, 0);
+
rtems_event_send(sc->sc_txtask, TX_TRANSMIT); /* Ready for the next Packet */
return(0);
}
@@ -647,10 +651,15 @@ pppstart(struct rtems_termios_tty *tp)
(*tp->handler.write)(ctx, (char *)sendBegin, (ioffset > 0) ? ioffset : 1);
sc->sc_stats.ppp_obytes += (ioffset > 0) ? ioffset : 1;
sc->sc_outoff += ioffset;
+
+ return (0);
}
}

- return ( 0 );
+ /* Notify driver that we have nothing to transmit */
+ (*tp->handler.write)(ctx, NULL, 0);
+
+ return (0);
}

#ifdef XXX_XXX
--
1.8.4.5
Sebastian Huber
2014-10-07 14:36:28 UTC
Permalink
Use the Termios device API.
---
c/src/lib/libbsp/arm/altera-cyclone-v/Makefile.am | 7 +-
.../arm/altera-cyclone-v/console/console-config.c | 159 +++--
c/src/lib/libbsp/arm/lpc176x/Makefile.am | 7 +-
.../libbsp/arm/lpc176x/console/console-config.c | 168 +++--
c/src/lib/libbsp/arm/lpc24xx/Makefile.am | 7 +-
.../libbsp/arm/lpc24xx/console/console-config.c | 151 +++--
.../lib/libbsp/arm/lpc24xx/console/uart-probe-1.c | 10 +-
.../lib/libbsp/arm/lpc24xx/console/uart-probe-2.c | 10 +-
.../lib/libbsp/arm/lpc24xx/console/uart-probe-3.c | 10 +-
c/src/lib/libbsp/arm/lpc24xx/include/bsp.h | 12 +-
c/src/lib/libbsp/arm/lpc32xx/Makefile.am | 12 +-
.../libbsp/arm/lpc32xx/console/console-config.c | 259 ++++----
c/src/lib/libbsp/arm/lpc32xx/console/hsu.c | 192 +++---
c/src/lib/libbsp/arm/lpc32xx/include/hsu.h | 68 +++
c/src/lib/libbsp/arm/lpc32xx/preinstall.am | 4 +
c/src/lib/libbsp/powerpc/gen83xx/Makefile.am | 10 +-
.../powerpc/gen83xx/console/console-config.c | 114 ++--
.../lib/libbsp/powerpc/gen83xx/startup/bspstart.c | 34 +-
c/src/lib/libbsp/powerpc/qoriq/Makefile.am | 14 +-
.../libbsp/powerpc/qoriq/console/console-config.c | 195 +++---
.../powerpc/qoriq/console/uart-bridge-master.c | 88 ++-
.../powerpc/qoriq/console/uart-bridge-slave.c | 114 ++--
.../lib/libbsp/powerpc/qoriq/include/uart-bridge.h | 18 +-
c/src/lib/libbsp/powerpc/qoriq/startup/bspstart.c | 40 +-
c/src/libchip/Makefile.am | 1 +
c/src/libchip/serial/ns16550-context.c | 677 +++++++++++++++++++++
c/src/libchip/serial/ns16550.c | 100 ++-
c/src/libchip/serial/ns16550.h | 32 +
c/src/libchip/serial/ns16550_p.h | 76 ---
29 files changed, 1640 insertions(+), 949 deletions(-)
create mode 100644 c/src/lib/libbsp/arm/lpc32xx/include/hsu.h
create mode 100644 c/src/libchip/serial/ns16550-context.c

diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/Makefile.am b/c/src/lib/libbsp/arm/altera-cyclone-v/Makefile.am
index fdae4f2..6e2d431 100644
--- a/c/src/lib/libbsp/arm/altera-cyclone-v/Makefile.am
+++ b/c/src/lib/libbsp/arm/altera-cyclone-v/Makefile.am
@@ -190,11 +190,8 @@ libbsp_a_SOURCES += ../shared/arm-gic-irq.c
libbsp_a_SOURCES += network/network.c

# Console
-libbsp_a_SOURCES += ../../shared/console.c
-libbsp_a_SOURCES += ../../shared/console_control.c
-libbsp_a_SOURCES += ../../shared/console_read.c
-libbsp_a_SOURCES += ../../shared/console_select_simple.c
-libbsp_a_SOURCES += ../../shared/console_write.c
+libbsp_a_SOURCES += ../../shared/console-termios-init.c
+libbsp_a_SOURCES += ../../shared/console-termios.c
libbsp_a_SOURCES += console/console-config.c

# Clock
diff --git a/c/src/lib/libbsp/arm/altera-cyclone-v/console/console-config.c b/c/src/lib/libbsp/arm/altera-cyclone-v/console/console-config.c
index c2a287c..5cc7849 100644
--- a/c/src/lib/libbsp/arm/altera-cyclone-v/console/console-config.c
+++ b/c/src/lib/libbsp/arm/altera-cyclone-v/console/console-config.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2013 embedded brains GmbH. All rights reserved.
+ * Copyright (c) 2013-2014 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
* Dornierstr. 4
@@ -12,28 +12,23 @@
* http://www.rtems.org/license/LICENSE.
*/

-#include <assert.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <libchip/serial.h>
#include <libchip/ns16550.h>

#include <bsp.h>
#include <bsp/irq.h>
#include <bsp/alt_clock_manager.h>
+#include <bsp/console-termios.h>
#include "socal/alt_rstmgr.h"
#include "socal/socal.h"
#include "socal/alt_uart.h"
#include "socal/hps.h"

#ifdef BSP_USE_UART_INTERRUPTS
- #define DEVICE_FNS &ns16550_fns
+ #define DEVICE_FNS &ns16550_handler_interrupt
#else
- #define DEVICE_FNS &ns16550_fns_polled
+ #define DEVICE_FNS &ns16550_handler_polled
#endif

-static bool altera_cyclone_v_uart_probe( int minor );
-
static uint8_t altera_cyclone_v_uart_get_register(uintptr_t addr, uint8_t i)
{
volatile uint32_t *reg = (volatile uint32_t *) addr;
@@ -48,92 +43,25 @@ static void altera_cyclone_v_uart_set_register(uintptr_t addr, uint8_t i, uint8_
reg [i] = val;
}

-console_tbl Console_Configuration_Ports[] = {
-#ifdef CYCLONE_V_CONFIG_CONSOLE
- {
- .sDeviceName = "/dev/ttyS0",
- .deviceType = SERIAL_NS16550,
- .pDeviceFns = DEVICE_FNS,
- .deviceProbe = altera_cyclone_v_uart_probe,
- .pDeviceFlow = NULL,
- .ulMargin = 16,
- .ulHysteresis = 8,
- .pDeviceParams = (void *)CYCLONE_V_UART_BAUD,
- .ulCtrlPort1 = (uint32_t)ALT_UART0_ADDR,
- .ulCtrlPort2 = 0,
- .ulDataPort = (uint32_t)ALT_UART0_ADDR,
- .getRegister = altera_cyclone_v_uart_get_register,
- .setRegister = altera_cyclone_v_uart_set_register,
- .getData = NULL,
- .setData = NULL,
- .ulClock = 0,
- .ulIntVector = ALT_INT_INTERRUPT_UART0
- },
-#endif
-#ifdef CYCLONE_V_CONFIG_UART_1
- {
- .sDeviceName = "/dev/ttyS1",
- .deviceType = SERIAL_NS16550,
- .pDeviceFns = DEVICE_FNS,
- .deviceProbe = altera_cyclone_v_uart_probe,
- .pDeviceFlow = NULL,
- .ulMargin = 16,
- .ulHysteresis = 8,
- .pDeviceParams = (void *)CYCLONE_V_UART_BAUD,
- .ulCtrlPort1 = (uint32_t)ALT_UART1_ADDR,
- .ulCtrlPort2 = 0,
- .ulDataPort = (uint32_t)ALT_UART1_ADDR,
- .getRegister = altera_cyclone_v_uart_get_register,
- .setRegister = altera_cyclone_v_uart_set_register,
- .getData = NULL,
- .setData = NULL,
- .ulClock = 0,
- .ulIntVector = ALT_INT_INTERRUPT_UART1
- }
-#endif
-};
-
-unsigned long Console_Configuration_Count =
- RTEMS_ARRAY_SIZE(Console_Configuration_Ports);
-
-bool altera_cyclone_v_uart_probe(int minor)
+static bool altera_cyclone_v_uart_probe(
+ rtems_termios_device_context *base,
+ uint32_t uart_set_mask
+)
{
+ ns16550_context *ctx = (ns16550_context *) base;
bool ret = true;
- uint32_t uart_set_mask;
uint32_t ucr;
ALT_STATUS_CODE sc;
- void* location;
+ void* location = (void *) ctx->port;

/* The ALT_CLK_L4_SP is required for all SoCFPGA UARTs.
* Check that it's enabled. */
- assert( alt_clk_is_enabled(ALT_CLK_L4_SP) == ALT_E_TRUE );
if ( alt_clk_is_enabled(ALT_CLK_L4_SP) != ALT_E_TRUE ) {
ret = false;
}

if ( ret ) {
- switch(minor)
- {
- case(0):
- /* UART 0 */
- uart_set_mask = ALT_RSTMGR_PERMODRST_UART0_SET_MSK;
- location = ALT_UART0_ADDR;
- break;
- case(1):
- /* UART 1 */
- uart_set_mask = ALT_RSTMGR_PERMODRST_UART1_SET_MSK;
- location = ALT_UART1_ADDR;
- break;
- default:
- /* Unknown case */
- assert( minor == 0 || minor == 1 );
- ret = false;
- break;
- }
- }
- if ( ret ) {
- sc = alt_clk_freq_get(ALT_CLK_L4_SP, &Console_Configuration_Ports[minor].ulClock);
- assert( sc == ALT_E_SUCCESS );
+ sc = alt_clk_freq_get(ALT_CLK_L4_SP, &ctx->clock);
if ( sc != ALT_E_SUCCESS ) {
ret = false;
}
@@ -145,8 +73,6 @@ bool altera_cyclone_v_uart_probe(int minor)

// Verify the UCR (UART Component Version)
ucr = alt_read_word( ALT_UART_UCV_ADDR( location ) );
-
- assert( ucr == ALT_UART_UCV_UART_COMPONENT_VER_RESET );
if ( ucr != ALT_UART_UCV_UART_COMPONENT_VER_RESET ) {
ret = false;
}
@@ -158,22 +84,75 @@ bool altera_cyclone_v_uart_probe(int minor)

// Read the MSR to work around case:119085.
(void)alt_read_word( ALT_UART_MSR_ADDR( location ) );
+
+ ret = ns16550_probe( base );
}

return ret;
}

+#ifdef CYCLONE_V_CONFIG_CONSOLE
+static bool altera_cyclone_v_uart_probe_0(rtems_termios_device_context *base)
+{
+ return altera_cyclone_v_uart_probe(base, ALT_RSTMGR_PERMODRST_UART0_SET_MSK);
+}
+
+static ns16550_context altera_cyclone_v_uart_context_0 = {
+ .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 0"),
+ .get_reg = altera_cyclone_v_uart_get_register,
+ .set_reg = altera_cyclone_v_uart_set_register,
+ .port = (uintptr_t) ALT_UART0_ADDR,
+ .irq = ALT_INT_INTERRUPT_UART0,
+ .initial_baud = CYCLONE_V_UART_BAUD
+};
+#endif
+
+#ifdef CYCLONE_V_CONFIG_CONSOLE
+static bool altera_cyclone_v_uart_probe_1(rtems_termios_device_context *base)
+{
+ return altera_cyclone_v_uart_probe(base, ALT_RSTMGR_PERMODRST_UART1_SET_MSK);
+}
+
+static ns16550_context altera_cyclone_v_uart_context_1 = {
+ .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 1"),
+ .get_reg = altera_cyclone_v_uart_get_register,
+ .set_reg = altera_cyclone_v_uart_set_register,
+ .port = (uintptr_t) ALT_UART1_ADDR,
+ .irq = ALT_INT_INTERRUPT_UART1,
+ .initial_baud = CYCLONE_V_UART_BAUD
+};
+#endif
+
+const console_device console_device_table[] = {
+ #ifdef CYCLONE_V_CONFIG_CONSOLE
+ {
+ .device_file = "/dev/ttyS0",
+ .probe = altera_cyclone_v_uart_probe_0,
+ .handler = DEVICE_FNS,
+ .context = &altera_cyclone_v_uart_context_0.base
+ },
+ #endif
+ #ifdef CYCLONE_V_CONFIG_UART_1
+ {
+ .device_file = "/dev/ttyS1",
+ .probe = altera_cyclone_v_uart_probe_1,
+ .handler = DEVICE_FNS,
+ .context = &altera_cyclone_v_uart_context_1.base
+ },
+ #endif
+};
+
+const size_t console_device_count = RTEMS_ARRAY_SIZE(console_device_table);
+
static void output_char(char c)
{
- int minor = (int) Console_Port_Minor;
- console_tbl *ct = Console_Port_Tbl != NULL ?
- Console_Port_Tbl[minor] : &Console_Configuration_Ports[minor];
+ rtems_termios_device_context *ctx = console_device_table[0].context;

if (c == '\n') {
- ns16550_outch_polled( ct, '\r' );
+ ns16550_polled_putchar( ctx, '\r' );
}

- ns16550_outch_polled( ct, c );
+ ns16550_polled_putchar( ctx, c );
}

BSP_output_char_function_type BSP_output_char = output_char;
diff --git a/c/src/lib/libbsp/arm/lpc176x/Makefile.am b/c/src/lib/libbsp/arm/lpc176x/Makefile.am
index bbd2fec..3f60f23 100644
--- a/c/src/lib/libbsp/arm/lpc176x/Makefile.am
+++ b/c/src/lib/libbsp/arm/lpc176x/Makefile.am
@@ -110,11 +110,8 @@ libbsp_a_SOURCES += ../shared/armv7m/irq/armv7m-irq-dispatch.c
libbsp_a_SOURCES += irq/irq.c

# Console
-libbsp_a_SOURCES += ../../shared/console.c
-libbsp_a_SOURCES += ../../shared/console_control.c
-libbsp_a_SOURCES += ../../shared/console_read.c
-libbsp_a_SOURCES += ../../shared/console_select.c
-libbsp_a_SOURCES += ../../shared/console_write.c
+libbsp_a_SOURCES += ../../shared/console-termios-init.c
+libbsp_a_SOURCES += ../../shared/console-termios.c
libbsp_a_SOURCES += console/console-config.c

# Clock
diff --git a/c/src/lib/libbsp/arm/lpc176x/console/console-config.c b/c/src/lib/libbsp/arm/lpc176x/console/console-config.c
index 246a9e6..3b56a2c 100644
--- a/c/src/lib/libbsp/arm/lpc176x/console/console-config.c
+++ b/c/src/lib/libbsp/arm/lpc176x/console/console-config.c
@@ -7,10 +7,10 @@
*/

/*
- * Copyright (c) 2008-2011 embedded brains GmbH. All rights reserved.
+ * Copyright (c) 2008-2014 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
- * Obere Lagerstr. 30
+ * Dornierstr. 4
* 82178 Puchheim
* Germany
* <rtems-L1vi/***@public.gmane.org>
@@ -20,12 +20,12 @@
* http://www.rtems.com/license/LICENSE.
*/

-#include <libchip/serial.h>
#include <libchip/ns16550.h>

#include <bsp.h>
#include <bsp/io.h>
#include <bsp/irq.h>
+#include <bsp/console-termios.h>

/**
* @brief Gets the uart register according to the current address.
@@ -62,97 +62,91 @@ static inline void lpc176x_uart_set_register(
reg[ i ] = val;
}

-/**
- * @brief Represents the uart configuration ports.
- */
-console_tbl Console_Configuration_Ports[] = {
#ifdef LPC176X_CONFIG_CONSOLE
- {
- .sDeviceName = "/dev/ttyS0",
- .deviceType = SERIAL_NS16550_WITH_FDR,
- .pDeviceFns = &ns16550_fns,
- .deviceProbe = NULL,
- .pDeviceFlow = NULL,
- .ulMargin = 16,
- .ulHysteresis = 8,
- .pDeviceParams = (void *) LPC176X_UART_BAUD,
- .ulCtrlPort1 = UART0_BASE_ADDR,
- .ulCtrlPort2 = 0,
- .ulDataPort = UART0_BASE_ADDR,
- .getRegister = lpc176x_uart_get_register,
- .setRegister = lpc176x_uart_set_register,
- .getData = NULL,
- .setData = NULL,
- .ulClock = LPC176X_PCLK,
- .ulIntVector = LPC176X_IRQ_UART_0
- },
+static ns16550_context lpc176x_uart_context_0 = {
+ .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 0"),
+ .get_reg = lpc176x_uart_get_register,
+ .set_reg = lpc176x_uart_set_register,
+ .port = UART0_BASE_ADDR,
+ .irq = LPC176X_IRQ_UART_0,
+ .clock = LPC176X_PCLK,
+ .initial_baud = LPC176X_UART_BAUD,
+ .has_fractional_divider_register = true
+};
#endif
+
#ifdef LPC176X_CONFIG_UART_1
- {
- .sDeviceName = "/dev/ttyS1",
- .deviceType = SERIAL_NS16550_WITH_FDR,
- .pDeviceFns = &ns16550_fns,
- .deviceProbe = lpc176x_uart_probe_1,
- .pDeviceFlow = NULL,
- .ulMargin = 16,
- .ulHysteresis = 8,
- .pDeviceParams = (void *) LPC176X_UART_BAUD,
- .ulCtrlPort1 = UART1_BASE_ADDR,
- .ulCtrlPort2 = 0,
- .ulDataPort = UART1_BASE_ADDR,
- .getRegister = lpc176x_uart_get_register,
- .setRegister = lpc176x_uart_set_register,
- .getData = NULL,
- .setData = NULL,
- .ulClock = LPC176X_PCLK,
- .ulIntVector = LPC176X_IRQ_UART_1
- },
+static ns16550_context lpc176x_uart_context_1 = {
+ .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 1"),
+ .get_reg = lpc176x_uart_get_register,
+ .set_reg = lpc176x_uart_set_register,
+ .port = UART1_BASE_ADDR,
+ .irq = LPC176X_IRQ_UART_1,
+ .clock = LPC176X_PCLK,
+ .initial_baud = LPC176X_UART_BAUD,
+ .has_fractional_divider_register = true
+};
#endif
+
#ifdef LPC176X_CONFIG_UART_2
- {
- .sDeviceName = "/dev/ttyS2",
- .deviceType = SERIAL_NS16550_WITH_FDR,
- .pDeviceFns = &ns16550_fns,
- .deviceProbe = lpc176x_uart_probe_2,
- .pDeviceFlow = NULL,
- .ulMargin = 16,
- .ulHysteresis = 8,
- .pDeviceParams = (void *) LPC176X_UART_BAUD,
- .ulCtrlPort1 = UART2_BASE_ADDR,
- .ulCtrlPort2 = 0,
- .ulDataPort = UART2_BASE_ADDR,
- .getRegister = lpc176x_uart_get_register,
- .setRegister = lpc176x_uart_set_register,
- .getData = NULL,
- .setData = NULL,
- .ulClock = LPC176X_PCLK,
- .ulIntVector = LPC176X_IRQ_UART_2
- },
+static ns16550_context lpc176x_uart_context_2 = {
+ .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 2"),
+ .get_reg = lpc176x_uart_get_register,
+ .set_reg = lpc176x_uart_set_register,
+ .port = UART2_BASE_ADDR,
+ .irq = LPC176X_IRQ_UART_2,
+ .clock = LPC176X_PCLK,
+ .initial_baud = LPC176X_UART_BAUD,
+ .has_fractional_divider_register = true
+};
#endif
+
#ifdef LPC176X_CONFIG_UART_3
- {
- .sDeviceName = "/dev/ttyS3",
- .deviceType = SERIAL_NS16550_WITH_FDR,
- .pDeviceFns = &ns16550_fns,
- .deviceProbe = lpc176x_uart_probe_3,
- .pDeviceFlow = NULL,
- .ulMargin = 16,
- .ulHysteresis = 8,
- .pDeviceParams = (void *) LPC176X_UART_BAUD,
- .ulCtrlPort1 = UART3_BASE_ADDR,
- .ulCtrlPort2 = 0,
- .ulDataPort = UART3_BASE_ADDR,
- .getRegister = lpc176x_uart_get_register,
- .setRegister = lpc176x_uart_set_register,
- .getData = NULL,
- .setData = NULL,
- .ulClock = LPC176X_PCLK,
- .ulIntVector = LPC176X_IRQ_UART_3
- },
-#endif
+static ns16550_context lpc176x_uart_context_3 = {
+ .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 3"),
+ .get_reg = lpc176x_uart_get_register,
+ .set_reg = lpc176x_uart_set_register,
+ .port = UART3_BASE_ADDR,
+ .irq = LPC176X_IRQ_UART_3,
+ .clock = LPC176X_PCLK,
+ .initial_baud = LPC176X_UART_BAUD,
+ .has_fractional_divider_register = true
};
+#endif

-#define LPC176X_UART_COUNT ( sizeof( Console_Configuration_Ports ) \
- / sizeof( Console_Configuration_Ports[ 0 ] ) )
+const console_device console_device_table[] = {
+ #ifdef LPC176X_CONFIG_CONSOLE
+ {
+ .device_file = "/dev/ttyS0",
+ .probe = console_device_probe_default,
+ .handler = &ns16550_handler_interrupt,
+ .context = &lpc176x_uart_context_0.base
+ },
+ #endif
+ #ifdef LPC176X_CONFIG_UART_1
+ {
+ .device_file = "/dev/ttyS1",
+ .probe = ns16550_probe,
+ .handler = &ns16550_handler_interrupt,
+ .context = &lpc176x_uart_context_1.base
+ },
+ #endif
+ #ifdef LPC176X_CONFIG_UART_2
+ {
+ .device_file = "/dev/ttyS2",
+ .probe = ns16550_probe,
+ .handler = &ns16550_handler_interrupt,
+ .context = &lpc176x_uart_context_2.base
+ },
+ #endif
+ #ifdef LPC176X_CONFIG_UART_3
+ {
+ .device_file = "/dev/ttyS3",
+ .probe = ns16550_probe,
+ .handler = &ns16550_handler_interrupt,
+ .context = &lpc176x_uart_context_3.base
+ },
+ #endif
+};

-unsigned long Console_Configuration_Count = LPC176X_UART_COUNT;
+const size_t console_device_count = RTEMS_ARRAY_SIZE(console_device_table);
diff --git a/c/src/lib/libbsp/arm/lpc24xx/Makefile.am b/c/src/lib/libbsp/arm/lpc24xx/Makefile.am
index 3ff85d6..c7fcb86 100644
--- a/c/src/lib/libbsp/arm/lpc24xx/Makefile.am
+++ b/c/src/lib/libbsp/arm/lpc24xx/Makefile.am
@@ -121,11 +121,8 @@ libbsp_a_SOURCES += irq/irq.c
libbsp_a_SOURCES += irq/irq-dispatch.c

# Console
-libbsp_a_SOURCES += ../../shared/console.c
-libbsp_a_SOURCES += ../../shared/console_control.c
-libbsp_a_SOURCES += ../../shared/console_read.c
-libbsp_a_SOURCES += ../../shared/console_select.c
-libbsp_a_SOURCES += ../../shared/console_write.c
+libbsp_a_SOURCES += ../../shared/console-termios-init.c
+libbsp_a_SOURCES += ../../shared/console-termios.c
libbsp_a_SOURCES += console/console-config.c
libbsp_a_SOURCES += console/uart-probe-1.c
libbsp_a_SOURCES += console/uart-probe-2.c
diff --git a/c/src/lib/libbsp/arm/lpc24xx/console/console-config.c b/c/src/lib/libbsp/arm/lpc24xx/console/console-config.c
index cce146f..de94552 100644
--- a/c/src/lib/libbsp/arm/lpc24xx/console/console-config.c
+++ b/c/src/lib/libbsp/arm/lpc24xx/console/console-config.c
@@ -7,10 +7,10 @@
*/

/*
- * Copyright (c) 2008-2011 embedded brains GmbH. All rights reserved.
+ * Copyright (c) 2008-2014 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
- * Obere Lagerstr. 30
+ * Dornierstr. 4
* 82178 Puchheim
* Germany
* <rtems-L1vi/***@public.gmane.org>
@@ -20,13 +20,15 @@
* http://www.rtems.org/license/LICENSE.
*/

-#include <libchip/serial.h>
+#include <rtems/console.h>
+
#include <libchip/ns16550.h>

#include <bsp.h>
#include <bsp/lpc24xx.h>
#include <bsp/irq.h>
#include <bsp/io.h>
+#include <bsp/console-termios.h>

static uint8_t lpc24xx_uart_get_register(uintptr_t addr, uint8_t i)
{
@@ -42,94 +44,91 @@ static void lpc24xx_uart_set_register(uintptr_t addr, uint8_t i, uint8_t val)
reg [i] = val;
}

-console_tbl Console_Configuration_Ports [] = {
+#ifdef LPC24XX_CONFIG_CONSOLE
+static ns16550_context lpc24xx_uart_context_0 = {
+ .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 0"),
+ .get_reg = lpc24xx_uart_get_register,
+ .set_reg = lpc24xx_uart_set_register,
+ .port = UART0_BASE_ADDR,
+ .irq = LPC24XX_IRQ_UART_0,
+ .clock = LPC24XX_PCLK,
+ .initial_baud = LPC24XX_UART_BAUD,
+ .has_fractional_divider_register = true
+};
+#endif
+
+#ifdef LPC24XX_CONFIG_UART_1
+static ns16550_context lpc24xx_uart_context_1 = {
+ .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 1"),
+ .get_reg = lpc24xx_uart_get_register,
+ .set_reg = lpc24xx_uart_set_register,
+ .port = UART1_BASE_ADDR,
+ .irq = LPC24XX_IRQ_UART_1,
+ .clock = LPC24XX_PCLK,
+ .initial_baud = LPC24XX_UART_BAUD,
+ .has_fractional_divider_register = true
+};
+#endif
+
+#ifdef LPC24XX_CONFIG_UART_2
+static ns16550_context lpc24xx_uart_context_2 = {
+ .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 2"),
+ .get_reg = lpc24xx_uart_get_register,
+ .set_reg = lpc24xx_uart_set_register,
+ .port = UART2_BASE_ADDR,
+ .irq = LPC24XX_IRQ_UART_2,
+ .clock = LPC24XX_PCLK,
+ .initial_baud = LPC24XX_UART_BAUD,
+ .has_fractional_divider_register = true
+};
+#endif
+
+#ifdef LPC24XX_CONFIG_UART_3
+static ns16550_context lpc24xx_uart_context_3 = {
+ .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 3"),
+ .get_reg = lpc24xx_uart_get_register,
+ .set_reg = lpc24xx_uart_set_register,
+ .port = UART3_BASE_ADDR,
+ .irq = LPC24XX_IRQ_UART_3,
+ .clock = LPC24XX_PCLK,
+ .initial_baud = LPC24XX_UART_BAUD,
+ .has_fractional_divider_register = true
+};
+#endif
+
+const console_device console_device_table[] = {
#ifdef LPC24XX_CONFIG_CONSOLE
{
- .sDeviceName = "/dev/ttyS0",
- .deviceType = SERIAL_NS16550_WITH_FDR,
- .pDeviceFns = &ns16550_fns,
- .deviceProbe = NULL,
- .pDeviceFlow = NULL,
- .ulMargin = 16,
- .ulHysteresis = 8,
- .pDeviceParams = (void *) LPC24XX_UART_BAUD,
- .ulCtrlPort1 = UART0_BASE_ADDR,
- .ulCtrlPort2 = 0,
- .ulDataPort = UART0_BASE_ADDR,
- .getRegister = lpc24xx_uart_get_register,
- .setRegister = lpc24xx_uart_set_register,
- .getData = NULL,
- .setData = NULL,
- .ulClock = LPC24XX_PCLK,
- .ulIntVector = LPC24XX_IRQ_UART_0
+ .device_file = "/dev/ttyS0",
+ .probe = console_device_probe_default,
+ .handler = &ns16550_handler_interrupt,
+ .context = &lpc24xx_uart_context_0.base
},
#endif
#ifdef LPC24XX_CONFIG_UART_1
{
- .sDeviceName = "/dev/ttyS1",
- .deviceType = SERIAL_NS16550_WITH_FDR,
- .pDeviceFns = &ns16550_fns,
- .deviceProbe = lpc24xx_uart_probe_1,
- .pDeviceFlow = NULL,
- .ulMargin = 16,
- .ulHysteresis = 8,
- .pDeviceParams = (void *) LPC24XX_UART_BAUD,
- .ulCtrlPort1 = UART1_BASE_ADDR,
- .ulCtrlPort2 = 0,
- .ulDataPort = UART1_BASE_ADDR,
- .getRegister = lpc24xx_uart_get_register,
- .setRegister = lpc24xx_uart_set_register,
- .getData = NULL,
- .setData = NULL,
- .ulClock = LPC24XX_PCLK,
- .ulIntVector = LPC24XX_IRQ_UART_1
+ .device_file = "/dev/ttyS1",
+ .probe = lpc24xx_uart_probe_1,
+ .handler = &ns16550_handler_interrupt,
+ .context = &lpc24xx_uart_context_1.base
},
#endif
#ifdef LPC24XX_CONFIG_UART_2
{
- .sDeviceName = "/dev/ttyS2",
- .deviceType = SERIAL_NS16550_WITH_FDR,
- .pDeviceFns = &ns16550_fns,
- .deviceProbe = lpc24xx_uart_probe_2,
- .pDeviceFlow = NULL,
- .ulMargin = 16,
- .ulHysteresis = 8,
- .pDeviceParams = (void *) LPC24XX_UART_BAUD,
- .ulCtrlPort1 = UART2_BASE_ADDR,
- .ulCtrlPort2 = 0,
- .ulDataPort = UART2_BASE_ADDR,
- .getRegister = lpc24xx_uart_get_register,
- .setRegister = lpc24xx_uart_set_register,
- .getData = NULL,
- .setData = NULL,
- .ulClock = LPC24XX_PCLK,
- .ulIntVector = LPC24XX_IRQ_UART_2
+ .device_file = "/dev/ttyS2",
+ .probe = lpc24xx_uart_probe_2,
+ .handler = &ns16550_handler_interrupt,
+ .context = &lpc24xx_uart_context_2.base
},
#endif
#ifdef LPC24XX_CONFIG_UART_3
{
- .sDeviceName = "/dev/ttyS3",
- .deviceType = SERIAL_NS16550_WITH_FDR,
- .pDeviceFns = &ns16550_fns,
- .deviceProbe = lpc24xx_uart_probe_3,
- .pDeviceFlow = NULL,
- .ulMargin = 16,
- .ulHysteresis = 8,
- .pDeviceParams = (void *) LPC24XX_UART_BAUD,
- .ulCtrlPort1 = UART3_BASE_ADDR,
- .ulCtrlPort2 = 0,
- .ulDataPort = UART3_BASE_ADDR,
- .getRegister = lpc24xx_uart_get_register,
- .setRegister = lpc24xx_uart_set_register,
- .getData = NULL,
- .setData = NULL,
- .ulClock = LPC24XX_PCLK,
- .ulIntVector = LPC24XX_IRQ_UART_3
+ .device_file = "/dev/ttyS3",
+ .probe = lpc24xx_uart_probe_3,
+ .handler = &ns16550_handler_interrupt,
+ .context = &lpc24xx_uart_context_3.base
},
#endif
};

-#define LPC24XX_UART_COUNT \
- (sizeof(Console_Configuration_Ports) \
- / sizeof(Console_Configuration_Ports [0]))
-unsigned long Console_Configuration_Count = LPC24XX_UART_COUNT;
+const size_t console_device_count = RTEMS_ARRAY_SIZE(console_device_table);
diff --git a/c/src/lib/libbsp/arm/lpc24xx/console/uart-probe-1.c b/c/src/lib/libbsp/arm/lpc24xx/console/uart-probe-1.c
index e3af151..3b5f080 100644
--- a/c/src/lib/libbsp/arm/lpc24xx/console/uart-probe-1.c
+++ b/c/src/lib/libbsp/arm/lpc24xx/console/uart-probe-1.c
@@ -7,10 +7,10 @@
*/

/*
- * Copyright (c) 2011-2013 embedded brains GmbH. All rights reserved.
+ * Copyright (c) 2011-2014 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
- * Obere Lagerstr. 30
+ * Dornierstr. 4
* 82178 Puchheim
* Germany
* <rtems-L1vi/***@public.gmane.org>
@@ -20,10 +20,12 @@
* http://www.rtems.org/license/LICENSE.
*/

+#include <libchip/ns16550.h>
+
#include <bsp.h>
#include <bsp/io.h>

-bool lpc24xx_uart_probe_1(int minor)
+bool lpc24xx_uart_probe_1(rtems_termios_device_context *context)
{
static const lpc24xx_pin_range pins [] = {
LPC24XX_PIN_UART_1_TXD_P0_15,
@@ -34,5 +36,5 @@ bool lpc24xx_uart_probe_1(int minor)
lpc24xx_module_enable(LPC24XX_MODULE_UART_1, LPC24XX_MODULE_PCLK_DEFAULT);
lpc24xx_pin_config(&pins [0], LPC24XX_PIN_SET_FUNCTION);

- return true;
+ return ns16550_probe(context);
}
diff --git a/c/src/lib/libbsp/arm/lpc24xx/console/uart-probe-2.c b/c/src/lib/libbsp/arm/lpc24xx/console/uart-probe-2.c
index 4f69d7f..d45dbb7 100644
--- a/c/src/lib/libbsp/arm/lpc24xx/console/uart-probe-2.c
+++ b/c/src/lib/libbsp/arm/lpc24xx/console/uart-probe-2.c
@@ -7,10 +7,10 @@
*/

/*
- * Copyright (c) 2011-2013 embedded brains GmbH. All rights reserved.
+ * Copyright (c) 2011-2014 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
- * Obere Lagerstr. 30
+ * Dornierstr. 4
* 82178 Puchheim
* Germany
* <rtems-L1vi/***@public.gmane.org>
@@ -20,10 +20,12 @@
* http://www.rtems.org/license/LICENSE.
*/

+#include <libchip/ns16550.h>
+
#include <bsp.h>
#include <bsp/io.h>

-bool lpc24xx_uart_probe_2(int minor)
+bool lpc24xx_uart_probe_2(rtems_termios_device_context *context)
{
static const lpc24xx_pin_range pins [] = {
LPC24XX_PIN_UART_2_TXD_P0_10,
@@ -34,5 +36,5 @@ bool lpc24xx_uart_probe_2(int minor)
lpc24xx_module_enable(LPC24XX_MODULE_UART_2, LPC24XX_MODULE_PCLK_DEFAULT);
lpc24xx_pin_config(&pins [0], LPC24XX_PIN_SET_FUNCTION);

- return true;
+ return ns16550_probe(context);
}
diff --git a/c/src/lib/libbsp/arm/lpc24xx/console/uart-probe-3.c b/c/src/lib/libbsp/arm/lpc24xx/console/uart-probe-3.c
index d71002f..fad932e 100644
--- a/c/src/lib/libbsp/arm/lpc24xx/console/uart-probe-3.c
+++ b/c/src/lib/libbsp/arm/lpc24xx/console/uart-probe-3.c
@@ -7,10 +7,10 @@
*/

/*
- * Copyright (c) 2011-2013 embedded brains GmbH. All rights reserved.
+ * Copyright (c) 2011-2014 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
- * Obere Lagerstr. 30
+ * Dornierstr. 4
* 82178 Puchheim
* Germany
* <rtems-L1vi/***@public.gmane.org>
@@ -20,10 +20,12 @@
* http://www.rtems.org/license/LICENSE.
*/

+#include <libchip/ns16550.h>
+
#include <bsp.h>
#include <bsp/io.h>

-bool lpc24xx_uart_probe_3(int minor)
+bool lpc24xx_uart_probe_3(rtems_termios_device_context *context)
{
static const lpc24xx_pin_range pins [] = {
LPC24XX_PIN_UART_3_TXD_P0_0,
@@ -34,5 +36,5 @@ bool lpc24xx_uart_probe_3(int minor)
lpc24xx_module_enable(LPC24XX_MODULE_UART_3, LPC24XX_MODULE_PCLK_DEFAULT);
lpc24xx_pin_config(&pins [0], LPC24XX_PIN_SET_FUNCTION);

- return true;
+ return ns16550_probe(context);
}
diff --git a/c/src/lib/libbsp/arm/lpc24xx/include/bsp.h b/c/src/lib/libbsp/arm/lpc24xx/include/bsp.h
index fad125a..e8c5d9a 100644
--- a/c/src/lib/libbsp/arm/lpc24xx/include/bsp.h
+++ b/c/src/lib/libbsp/arm/lpc24xx/include/bsp.h
@@ -7,10 +7,10 @@
*/

/*
- * Copyright (c) 2008-2013 embedded brains GmbH. All rights reserved.
+ * Copyright (c) 2008-2014 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
- * Obere Lagerstr. 30
+ * Dornierstr. 4
* 82178 Puchheim
* Germany
* <rtems-L1vi/***@public.gmane.org>
@@ -53,6 +53,8 @@ extern "C" {

struct rtems_bsdnet_ifconfig;

+struct rtems_termios_device_context;
+
/**
* @defgroup lpc24xx LPC24XX Support
*
@@ -111,11 +113,11 @@ void *bsp_idle_thread(uintptr_t ignored);

void bsp_restart(void *addr);

-bool lpc24xx_uart_probe_1(int minor);
+bool lpc24xx_uart_probe_1(struct rtems_termios_device_context *context);

-bool lpc24xx_uart_probe_2(int minor);
+bool lpc24xx_uart_probe_2(struct rtems_termios_device_context *context);

-bool lpc24xx_uart_probe_3(int minor);
+bool lpc24xx_uart_probe_3(struct rtems_termios_device_context *context);

/** @} */

diff --git a/c/src/lib/libbsp/arm/lpc32xx/Makefile.am b/c/src/lib/libbsp/arm/lpc32xx/Makefile.am
index 0eef512..524d07e 100644
--- a/c/src/lib/libbsp/arm/lpc32xx/Makefile.am
+++ b/c/src/lib/libbsp/arm/lpc32xx/Makefile.am
@@ -48,6 +48,7 @@ include_bsp_HEADERS += include/lpc-clock-config.h
include_bsp_HEADERS += include/lpc-ethernet-config.h
include_bsp_HEADERS += include/nand-mlc.h
include_bsp_HEADERS += include/boot.h
+include_bsp_HEADERS += include/hsu.h
include_bsp_HEADERS += include/i2c.h
include_bsp_HEADERS += include/emc.h

@@ -111,13 +112,10 @@ libbsp_a_SOURCES += ../../shared/src/irq-shell.c
libbsp_a_SOURCES += irq/irq.c

# Console
-libbsp_a_SOURCES += ../../shared/console.c \
- ../../shared/console_select.c \
- console/console-config.c \
- console/hsu.c \
- ../../shared/console_read.c \
- ../../shared/console_write.c \
- ../../shared/console_control.c
+libbsp_a_SOURCES += ../../shared/console-termios-init.c
+libbsp_a_SOURCES += ../../shared/console-termios.c
+libbsp_a_SOURCES += console/console-config.c
+libbsp_a_SOURCES += console/hsu.c

# Clock
libbsp_a_SOURCES += ../shared/lpc/clock/lpc-clock-config.c
diff --git a/c/src/lib/libbsp/arm/lpc32xx/console/console-config.c b/c/src/lib/libbsp/arm/lpc32xx/console/console-config.c
index d288985..17e6b0a 100644
--- a/c/src/lib/libbsp/arm/lpc32xx/console/console-config.c
+++ b/c/src/lib/libbsp/arm/lpc32xx/console/console-config.c
@@ -7,26 +7,26 @@
*/

/*
- * Copyright (c) 2009
- * embedded brains GmbH
- * Obere Lagerstr. 30
- * D-82178 Puchheim
- * Germany
- * <rtems-L1vi/***@public.gmane.org>
+ * Copyright (c) 2009-2014 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Dornierstr. 4
+ * 82178 Puchheim
+ * Germany
+ * <rtems-L1vi/***@public.gmane.org>
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/

-#include <libchip/serial.h>
#include <libchip/ns16550.h>

#include <bsp.h>
#include <bsp/lpc32xx.h>
#include <bsp/irq.h>
-
-extern const console_fns lpc32xx_hsu_fns;
+#include <bsp/hsu.h>
+#include <bsp/console-termios.h>

static uint8_t lpc32xx_uart_get_register(uintptr_t addr, uint8_t i)
{
@@ -43,18 +43,18 @@ static void lpc32xx_uart_set_register(uintptr_t addr, uint8_t i, uint8_t val)
}

#ifdef LPC32XX_UART_3_BAUD
- static bool lpc32xx_uart_probe_3(int minor)
+ static bool lpc32xx_uart_probe_3(rtems_termios_device_context *context)
{
LPC32XX_UARTCLK_CTRL |= BSP_BIT32(0);
LPC32XX_U3CLK = LPC32XX_CONFIG_U3CLK;
LPC32XX_UART_CLKMODE = BSP_FLD32SET(LPC32XX_UART_CLKMODE, 0x2, 4, 5);

- return true;
+ return ns16550_probe(context);
}
#endif

#ifdef LPC32XX_UART_4_BAUD
- static bool lpc32xx_uart_probe_4(int minor)
+ static bool lpc32xx_uart_probe_4(rtems_termios_device_context *context)
{
volatile lpc32xx_gpio *gpio = &lpc32xx.gpio;

@@ -68,12 +68,12 @@ static void lpc32xx_uart_set_register(uintptr_t addr, uint8_t i, uint8_t val)
LPC32XX_U4CLK = LPC32XX_CONFIG_U4CLK;
LPC32XX_UART_CLKMODE = BSP_FLD32SET(LPC32XX_UART_CLKMODE, 0x2, 6, 7);

- return true;
+ return ns16550_probe(context);
}
#endif

#ifdef LPC32XX_UART_6_BAUD
- static bool lpc32xx_uart_probe_6(int minor)
+ static bool lpc32xx_uart_probe_6(rtems_termios_device_context *context)
{
/* Bypass the IrDA modulator/demodulator */
LPC32XX_UART_CTRL |= BSP_BIT32(5);
@@ -82,163 +82,144 @@ static void lpc32xx_uart_set_register(uintptr_t addr, uint8_t i, uint8_t val)
LPC32XX_U6CLK = LPC32XX_CONFIG_U6CLK;
LPC32XX_UART_CLKMODE = BSP_FLD32SET(LPC32XX_UART_CLKMODE, 0x2, 10, 11);

- return true;
+ return ns16550_probe(context);
}
#endif

/* FIXME: Console selection */

-console_tbl Console_Configuration_Ports [] = {
+#ifdef LPC32XX_UART_5_BAUD
+static ns16550_context lpc32xx_uart_context_5 = {
+ .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 5"),
+ .get_reg = lpc32xx_uart_get_register,
+ .set_reg = lpc32xx_uart_set_register,
+ .port = LPC32XX_BASE_UART_5,
+ .irq = LPC32XX_IRQ_UART_5,
+ .clock = 16 * LPC32XX_UART_5_BAUD,
+ .initial_baud = LPC32XX_UART_5_BAUD
+};
+#endif
+
+#ifdef LPC32XX_UART_3_BAUD
+static ns16550_context lpc32xx_uart_context_3 = {
+ .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 3"),
+ .get_reg = lpc32xx_uart_get_register,
+ .set_reg = lpc32xx_uart_set_register,
+ .port = LPC32XX_BASE_UART_3,
+ .irq = LPC32XX_IRQ_UART_3,
+ .clock = 16 * LPC32XX_UART_3_BAUD,
+ .initial_baud = LPC32XX_UART_3_BAUD
+};
+#endif
+
+#ifdef LPC32XX_UART_4_BAUD
+static ns16550_context lpc32xx_uart_context_4 = {
+ .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 4"),
+ .get_reg = lpc32xx_uart_get_register,
+ .set_reg = lpc32xx_uart_set_register,
+ .port = LPC32XX_BASE_UART_4,
+ .irq = LPC32XX_IRQ_UART_4,
+ .clock = 16 * LPC32XX_UART_4_BAUD,
+ .initial_baud = LPC32XX_UART_4_BAUD
+};
+#endif
+
+#ifdef LPC32XX_UART_6_BAUD
+static ns16550_context lpc32xx_uart_context_6 = {
+ .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 6"),
+ .get_reg = lpc32xx_uart_get_register,
+ .set_reg = lpc32xx_uart_set_register,
+ .port = LPC32XX_BASE_UART_6,
+ .irq = LPC32XX_IRQ_UART_6,
+ .clock = 16 * LPC32XX_UART_6_BAUD,
+ .initial_baud = LPC32XX_UART_6_BAUD
+};
+#endif
+
+#ifdef LPC32XX_UART_1_BAUD
+static lpc32xx_hsu_context lpc32xx_uart_context_1 = {
+ .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 1"),
+ .hsu = (volatile lpc32xx_hsu *) LPC32XX_BASE_UART_1,
+ .irq = LPC32XX_IRQ_UART_1,
+ .initial_baud = LPC32XX_UART_1_BAUD
+};
+#endif
+
+#ifdef LPC32XX_UART_2_BAUD
+static lpc32xx_hsu_context lpc32xx_uart_context_2 = {
+ .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 2"),
+ .hsu = (volatile lpc32xx_hsu *) LPC32XX_BASE_UART_2,
+ .irq = LPC32XX_IRQ_UART_2,
+ .initial_baud = LPC32XX_UART_2_BAUD
+};
+#endif
+
+#ifdef LPC32XX_UART_7_BAUD
+static lpc32xx_hsu_context lpc32xx_uart_context_7 = {
+ .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 7"),
+ .hsu = (volatile lpc32xx_hsu *) LPC32XX_BASE_UART_7,
+ .irq = LPC32XX_IRQ_UART_7,
+ .initial_baud = LPC32XX_UART_7_BAUD
+};
+#endif
+
+const console_device console_device_table[] = {
#ifdef LPC32XX_UART_5_BAUD
{
- .sDeviceName = "/dev/ttyS5",
- .deviceType = SERIAL_NS16550,
- .pDeviceFns = &ns16550_fns,
- .deviceProbe = NULL,
- .pDeviceFlow = NULL,
- .ulMargin = 16,
- .ulHysteresis = 8,
- .pDeviceParams = (void *) LPC32XX_UART_5_BAUD,
- .ulCtrlPort1 = LPC32XX_BASE_UART_5,
- .ulCtrlPort2 = 0,
- .ulDataPort = LPC32XX_BASE_UART_5,
- .getRegister = lpc32xx_uart_get_register,
- .setRegister = lpc32xx_uart_set_register,
- .getData = NULL,
- .setData = NULL,
- .ulClock = 16 * LPC32XX_UART_5_BAUD,
- .ulIntVector = LPC32XX_IRQ_UART_5
+ .device_file = "/dev/ttyS5",
+ .probe = console_device_probe_default,
+ .handler = &ns16550_handler_interrupt,
+ .context = &lpc32xx_uart_context_5.base
},
#endif
#ifdef LPC32XX_UART_3_BAUD
{
- .sDeviceName = "/dev/ttyS3",
- .deviceType = SERIAL_NS16550,
- .pDeviceFns = &ns16550_fns,
- .deviceProbe = lpc32xx_uart_probe_3,
- .pDeviceFlow = NULL,
- .ulMargin = 16,
- .ulHysteresis = 8,
- .pDeviceParams = (void *) LPC32XX_UART_3_BAUD,
- .ulCtrlPort1 = LPC32XX_BASE_UART_3,
- .ulCtrlPort2 = 0,
- .ulDataPort = LPC32XX_BASE_UART_3,
- .getRegister = lpc32xx_uart_get_register,
- .setRegister = lpc32xx_uart_set_register,
- .getData = NULL,
- .setData = NULL,
- .ulClock = 16 * LPC32XX_UART_3_BAUD,
- .ulIntVector = LPC32XX_IRQ_UART_3
+ .device_file = "/dev/ttyS3",
+ .probe = lpc32xx_uart_probe_3,
+ .handler = &ns16550_handler_interrupt,
+ .context = &lpc32xx_uart_context_3.base
},
#endif
#ifdef LPC32XX_UART_4_BAUD
{
- .sDeviceName = "/dev/ttyS4",
- .deviceType = SERIAL_NS16550,
- .pDeviceFns = &ns16550_fns,
- .deviceProbe = lpc32xx_uart_probe_4,
- .pDeviceFlow = NULL,
- .ulMargin = 16,
- .ulHysteresis = 8,
- .pDeviceParams = (void *) LPC32XX_UART_4_BAUD,
- .ulCtrlPort1 = LPC32XX_BASE_UART_4,
- .ulCtrlPort2 = 0,
- .ulDataPort = LPC32XX_BASE_UART_4,
- .getRegister = lpc32xx_uart_get_register,
- .setRegister = lpc32xx_uart_set_register,
- .getData = NULL,
- .setData = NULL,
- .ulClock = 16 * LPC32XX_UART_4_BAUD,
- .ulIntVector = LPC32XX_IRQ_UART_4
+ .device_file = "/dev/ttyS4",
+ .probe = lpc32xx_uart_probe_4,
+ .handler = &ns16550_handler_interrupt,
+ .context = &lpc32xx_uart_context_4.base
},
#endif
#ifdef LPC32XX_UART_6_BAUD
{
- .sDeviceName = "/dev/ttyS6",
- .deviceType = SERIAL_NS16550,
- .pDeviceFns = &ns16550_fns,
- .deviceProbe = lpc32xx_uart_probe_6,
- .pDeviceFlow = NULL,
- .ulMargin = 16,
- .ulHysteresis = 8,
- .pDeviceParams = (void *) LPC32XX_UART_6_BAUD,
- .ulCtrlPort1 = LPC32XX_BASE_UART_6,
- .ulCtrlPort2 = 0,
- .ulDataPort = LPC32XX_BASE_UART_6,
- .getRegister = lpc32xx_uart_get_register,
- .setRegister = lpc32xx_uart_set_register,
- .getData = NULL,
- .setData = NULL,
- .ulClock = 16 * LPC32XX_UART_6_BAUD,
- .ulIntVector = LPC32XX_IRQ_UART_6
+ .device_file = "/dev/ttyS6",
+ .probe = lpc32xx_uart_probe_6,
+ .handler = &ns16550_handler_interrupt,
+ .context = &lpc32xx_uart_context_6.base
},
#endif
#ifdef LPC32XX_UART_1_BAUD
{
- .sDeviceName = "/dev/ttyS1",
- .deviceType = SERIAL_CUSTOM,
- .pDeviceFns = &lpc32xx_hsu_fns,
- .deviceProbe = NULL,
- .pDeviceFlow = NULL,
- .ulMargin = 16,
- .ulHysteresis = 8,
- .pDeviceParams = (void *) LPC32XX_UART_1_BAUD,
- .ulCtrlPort1 = LPC32XX_BASE_UART_1,
- .ulCtrlPort2 = 0,
- .ulDataPort = 0,
- .getRegister = NULL,
- .setRegister = NULL,
- .getData = NULL,
- .setData = NULL,
- .ulClock = 16,
- .ulIntVector = LPC32XX_IRQ_UART_1
+ .device_file = "/dev/ttyS1",
+ .probe = lpc32xx_hsu_probe,
+ .handler = &lpc32xx_hsu_fns,
+ .context = &lpc32xx_uart_context_1.base
},
#endif
#ifdef LPC32XX_UART_2_BAUD
{
- .sDeviceName = "/dev/ttyS2",
- .deviceType = SERIAL_CUSTOM,
- .pDeviceFns = &lpc32xx_hsu_fns,
- .deviceProbe = NULL,
- .pDeviceFlow = NULL,
- .ulMargin = 16,
- .ulHysteresis = 8,
- .pDeviceParams = (void *) LPC32XX_UART_2_BAUD,
- .ulCtrlPort1 = LPC32XX_BASE_UART_2,
- .ulCtrlPort2 = 0,
- .ulDataPort = 0,
- .getRegister = NULL,
- .setRegister = NULL,
- .getData = NULL,
- .setData = NULL,
- .ulClock = 16,
- .ulIntVector = LPC32XX_IRQ_UART_2
+ .device_file = "/dev/ttyS2",
+ .probe = lpc32xx_hsu_probe,
+ .handler = &lpc32xx_hsu_fns,
+ .context = &lpc32xx_uart_context_2.base
},
#endif
#ifdef LPC32XX_UART_7_BAUD
{
- .sDeviceName = "/dev/ttyS7",
- .deviceType = SERIAL_CUSTOM,
- .pDeviceFns = &lpc32xx_hsu_fns,
- .deviceProbe = NULL,
- .pDeviceFlow = NULL,
- .ulMargin = 16,
- .ulHysteresis = 8,
- .pDeviceParams = (void *) LPC32XX_UART_7_BAUD,
- .ulCtrlPort1 = LPC32XX_BASE_UART_7,
- .ulCtrlPort2 = 0,
- .ulDataPort = 0,
- .getRegister = NULL,
- .setRegister = NULL,
- .getData = NULL,
- .setData = NULL,
- .ulClock = 16,
- .ulIntVector = LPC32XX_IRQ_UART_7
+ .device_file = "/dev/ttyS7",
+ .probe = lpc32xx_hsu_probe,
+ .handler = &lpc32xx_hsu_fns,
+ .context = &lpc32xx_uart_context_7.base
},
#endif
};

-#define LPC32XX_UART_COUNT \
- (sizeof(Console_Configuration_Ports) / sizeof(Console_Configuration_Ports [0]))
-
-unsigned long Console_Configuration_Count = LPC32XX_UART_COUNT;
+const size_t console_device_count = RTEMS_ARRAY_SIZE(console_device_table);
diff --git a/c/src/lib/libbsp/arm/lpc32xx/console/hsu.c b/c/src/lib/libbsp/arm/lpc32xx/console/hsu.c
index 0dc4a61..8beeeef 100644
--- a/c/src/lib/libbsp/arm/lpc32xx/console/hsu.c
+++ b/c/src/lib/libbsp/arm/lpc32xx/console/hsu.c
@@ -7,36 +7,23 @@
*/

/*
- * Copyright (c) 2010
- * embedded brains GmbH
- * Obere Lagerstr. 30
- * D-82178 Puchheim
- * Germany
- * <rtems-L1vi/***@public.gmane.org>
+ * Copyright (c) 2010-2014 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Dornierstr. 4
+ * 82178 Puchheim
+ * Germany
+ * <rtems-L1vi/***@public.gmane.org>
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rtems.org/license/LICENSE.
*/

-#include <rtems.h>
-#include <rtems/libio.h>
-#include <rtems/termiostypes.h>
-
-#include <libchip/serial.h>
-#include <libchip/sersupp.h>
-
#include <bsp.h>
#include <bsp/lpc32xx.h>
#include <bsp/irq.h>
-
-typedef struct {
- uint32_t fifo;
- uint32_t level;
- uint32_t iir;
- uint32_t ctrl;
- uint32_t rate;
-} lpc32xx_hsu;
+#include <bsp/hsu.h>

#define HSU_FIFO_SIZE 64

@@ -60,54 +47,29 @@ typedef struct {
/* We are interested in RX timeout, RX trigger and TX trigger interrupts */
#define HSU_IIR_MASK 0x7U

-static int lpc32xx_hsu_first_open(int major, int minor, void *arg)
-{
- rtems_libio_open_close_args_t *oca = arg;
- struct rtems_termios_tty *tty = oca->iop->data1;
- console_tbl *ct = Console_Port_Tbl [minor];
- console_data *cd = &Console_Port_Data [minor];
- volatile lpc32xx_hsu *hsu = (volatile lpc32xx_hsu *) ct->ulCtrlPort1;
-
- cd->termios_data = tty;
- rtems_termios_set_initial_baud(tty, (int32_t) ct->pDeviceParams);
- hsu->ctrl = HSU_CTRL_RX_INTR_ENABLED;
-
- return 0;
-}
-
-static ssize_t lpc32xx_hsu_write(int minor, const char *buf, size_t len)
+bool lpc32xx_hsu_probe(rtems_termios_device_context *base)
{
- console_tbl *ct = Console_Port_Tbl [minor];
- console_data *cd = &Console_Port_Data [minor];
- volatile lpc32xx_hsu *hsu = (volatile lpc32xx_hsu *) ct->ulCtrlPort1;
- size_t tx_level = (hsu->level & HSU_LEVEL_TX_MASK) >> HSU_LEVEL_TX_SHIFT;
- size_t tx_free = HSU_FIFO_SIZE - tx_level;
- size_t i = 0;
- size_t out = len > tx_free ? tx_free : len;
+ lpc32xx_hsu_context *ctx = (lpc32xx_hsu_context *) base;
+ volatile lpc32xx_hsu *hsu = ctx->hsu;

- for (i = 0; i < out; ++i) {
- hsu->fifo = buf [i];
- }
+ hsu->ctrl = HSU_CTRL_INTR_DISABLED;

- if (len > 0) {
- cd->pDeviceContext = (void *) out;
- cd->bActive = true;
- hsu->ctrl = HSU_CTRL_RX_AND_TX_INTR_ENABLED;
+ /* Drain FIFOs */
+ while (hsu->level != 0) {
+ hsu->fifo;
}

- return 0;
+ return true;
}

static void lpc32xx_hsu_interrupt_handler(void *arg)
{
- int minor = (int) arg;
- console_tbl *ct = Console_Port_Tbl [minor];
- console_data *cd = &Console_Port_Data [minor];
- volatile lpc32xx_hsu *hsu = (volatile lpc32xx_hsu *) ct->ulCtrlPort1;
+ rtems_termios_tty *tty = arg;
+ lpc32xx_hsu_context *ctx = rtems_termios_get_device_context(tty);
+ volatile lpc32xx_hsu *hsu = ctx->hsu;

/* Iterate until no more interrupts are pending */
do {
- int chars_to_dequeue = (int) cd->pDeviceContext;
int rv = 0;
int i = 0;
char buf [HSU_FIFO_SIZE];
@@ -125,49 +87,97 @@ static void lpc32xx_hsu_interrupt_handler(void *arg)
break;
}
}
- rtems_termios_enqueue_raw_characters(cd->termios_data, buf, i);
+ rtems_termios_enqueue_raw_characters(tty, buf, i);

/* Dequeue transmitted characters */
- cd->pDeviceContext = 0;
- rv = rtems_termios_dequeue_characters(cd->termios_data, chars_to_dequeue);
+ rv = rtems_termios_dequeue_characters(tty, (int) ctx->chars_in_transmission);
if (rv == 0) {
/* Nothing to transmit */
- cd->bActive = false;
- hsu->ctrl = HSU_CTRL_RX_INTR_ENABLED;
- hsu->iir = HSU_IIR_TX;
}
} while ((hsu->iir & HSU_IIR_MASK) != 0);
}

-static void lpc32xx_hsu_initialize(int minor)
+static bool lpc32xx_hsu_first_open(
+ struct rtems_termios_tty *tty,
+ rtems_termios_device_context *base,
+ struct termios *term,
+ rtems_libio_open_close_args_t *args
+)
{
- console_tbl *ct = Console_Port_Tbl [minor];
- console_data *cd = &Console_Port_Data [minor];
- volatile lpc32xx_hsu *hsu = (volatile lpc32xx_hsu *) ct->ulCtrlPort1;
-
- hsu->ctrl = HSU_CTRL_INTR_DISABLED;
+ lpc32xx_hsu_context *ctx = (lpc32xx_hsu_context *) base;
+ volatile lpc32xx_hsu *hsu = ctx->hsu;
+ rtems_status_code sc;
+ bool ok;

- cd->bActive = false;
- cd->pDeviceContext = 0;
+ sc = rtems_interrupt_handler_install(
+ ctx->irq,
+ "HSU",
+ RTEMS_INTERRUPT_UNIQUE,
+ lpc32xx_hsu_interrupt_handler,
+ tty
+ );
+ ok = sc == RTEMS_SUCCESSFUL;

- /* Drain FIFOs */
- while (hsu->level != 0) {
- hsu->fifo;
+ if (ok) {
+ rtems_termios_set_initial_baud(tty, ctx->initial_baud);
+ hsu->ctrl = HSU_CTRL_RX_INTR_ENABLED;
}

- rtems_interrupt_handler_install(
- ct->ulIntVector,
- "HSU",
- RTEMS_INTERRUPT_UNIQUE,
+ return ok;
+}
+
+static void lpc32xx_hsu_last_close(
+ struct rtems_termios_tty *tty,
+ rtems_termios_device_context *base,
+ rtems_libio_open_close_args_t *args
+)
+{
+ lpc32xx_hsu_context *ctx = (lpc32xx_hsu_context *) base;
+ volatile lpc32xx_hsu *hsu = ctx->hsu;
+
+ hsu->ctrl = HSU_CTRL_INTR_DISABLED;
+
+ rtems_interrupt_handler_remove(
+ ctx->irq,
lpc32xx_hsu_interrupt_handler,
- (void *) minor
+ tty
);
}

-static int lpc32xx_hsu_set_attributes(int minor, const struct termios *term)
+static void lpc32xx_hsu_write(
+ rtems_termios_device_context *base,
+ const char *buf,
+ size_t len
+)
+{
+ lpc32xx_hsu_context *ctx = (lpc32xx_hsu_context *) base;
+ volatile lpc32xx_hsu *hsu = ctx->hsu;
+ size_t tx_level = (hsu->level & HSU_LEVEL_TX_MASK) >> HSU_LEVEL_TX_SHIFT;
+ size_t tx_free = HSU_FIFO_SIZE - tx_level;
+ size_t i = 0;
+ size_t out = len > tx_free ? tx_free : len;
+
+ for (i = 0; i < out; ++i) {
+ hsu->fifo = buf [i];
+ }
+
+ ctx->chars_in_transmission = out;
+
+ if (len > 0) {
+ hsu->ctrl = HSU_CTRL_RX_AND_TX_INTR_ENABLED;
+ } else {
+ hsu->ctrl = HSU_CTRL_RX_INTR_ENABLED;
+ hsu->iir = HSU_IIR_TX;
+ }
+}
+
+static bool lpc32xx_hsu_set_attributes(
+ rtems_termios_device_context *base,
+ const struct termios *term
+)
{
- console_tbl *ct = Console_Port_Tbl [minor];
- volatile lpc32xx_hsu *hsu = (volatile lpc32xx_hsu *) ct->ulCtrlPort1;
+ lpc32xx_hsu_context *ctx = (lpc32xx_hsu_context *) base;
+ volatile lpc32xx_hsu *hsu = ctx->hsu;
int baud_flags = term->c_cflag & CBAUD;

if (baud_flags != 0) {
@@ -186,17 +196,13 @@ static int lpc32xx_hsu_set_attributes(int minor, const struct termios *term)
}
}

- return 0;
+ return true;
}

-const console_fns lpc32xx_hsu_fns = {
- .deviceProbe = libchip_serial_default_probe,
- .deviceFirstOpen = lpc32xx_hsu_first_open,
- .deviceLastClose = NULL,
- .deviceRead = NULL,
- .deviceWrite = lpc32xx_hsu_write,
- .deviceInitialize = lpc32xx_hsu_initialize,
- .deviceWritePolled = NULL,
- .deviceSetAttributes = lpc32xx_hsu_set_attributes,
- .deviceOutputUsesInterrupts = true
+const rtems_termios_device_handler lpc32xx_hsu_fns = {
+ .first_open = lpc32xx_hsu_first_open,
+ .last_close = lpc32xx_hsu_last_close,
+ .write = lpc32xx_hsu_write,
+ .set_attributes = lpc32xx_hsu_set_attributes,
+ .mode = TERMIOS_IRQ_DRIVEN
};
diff --git a/c/src/lib/libbsp/arm/lpc32xx/include/hsu.h b/c/src/lib/libbsp/arm/lpc32xx/include/hsu.h
new file mode 100644
index 0000000..ba97dfb
--- /dev/null
+++ b/c/src/lib/libbsp/arm/lpc32xx/include/hsu.h
@@ -0,0 +1,68 @@
+/**
+ * @file
+ *
+ * @ingroup lpc32xx_hsu
+ *
+ * @brief HSU support API.
+ */
+
+/*
+ * Copyright (c) 2010-2014 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Dornierstr. 4
+ * 82178 Puchheim
+ * Germany
+ * <rtems-L1vi/***@public.gmane.org>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#ifndef LIBBSP_ARM_LPC32XX_HSU_H
+#define LIBBSP_ARM_LPC32XX_HSU_H
+
+#include <rtems/termiostypes.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @defgroup lpc32xx_hsu HSU Support
+ *
+ * @ingroup arm_lpc32xx
+ *
+ * @brief HSU Support
+ *
+ * @{
+ */
+
+typedef struct {
+ uint32_t fifo;
+ uint32_t level;
+ uint32_t iir;
+ uint32_t ctrl;
+ uint32_t rate;
+} lpc32xx_hsu;
+
+typedef struct {
+ rtems_termios_device_context base;
+ volatile lpc32xx_hsu *hsu;
+ size_t chars_in_transmission;
+ rtems_vector_number irq;
+ uint32_t initial_baud;
+} lpc32xx_hsu_context;
+
+extern const rtems_termios_device_handler lpc32xx_hsu_fns;
+
+bool lpc32xx_hsu_probe(rtems_termios_device_context *base);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* LIBBSP_ARM_LPC32XX_HSU_H */
diff --git a/c/src/lib/libbsp/arm/lpc32xx/preinstall.am b/c/src/lib/libbsp/arm/lpc32xx/preinstall.am
index b15e8cd..9a2571e 100644
--- a/c/src/lib/libbsp/arm/lpc32xx/preinstall.am
+++ b/c/src/lib/libbsp/arm/lpc32xx/preinstall.am
@@ -146,6 +146,10 @@ $(PROJECT_INCLUDE)/bsp/boot.h: include/boot.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/boot.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/boot.h

+$(PROJECT_INCLUDE)/bsp/hsu.h: include/hsu.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
+ $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/hsu.h
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/hsu.h
+
$(PROJECT_INCLUDE)/bsp/i2c.h: include/i2c.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/i2c.h
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/i2c.h
diff --git a/c/src/lib/libbsp/powerpc/gen83xx/Makefile.am b/c/src/lib/libbsp/powerpc/gen83xx/Makefile.am
index 3e24d30..35a093b 100644
--- a/c/src/lib/libbsp/powerpc/gen83xx/Makefile.am
+++ b/c/src/lib/libbsp/powerpc/gen83xx/Makefile.am
@@ -82,12 +82,10 @@ libbsp_a_SOURCES += ../../shared/src/irq-shell.c
libbsp_a_SOURCES += irq/irq.c

# console
-libbsp_a_SOURCES += ../../shared/console.c \
- ../../shared/console_select.c \
- console/console-config.c \
- ../../shared/console_read.c \
- ../../shared/console_write.c \
- ../../shared/console_control.c
+libbsp_a_SOURCES += ../../shared/console-termios-init.c
+libbsp_a_SOURCES += ../../shared/console-termios.c
+libbsp_a_SOURCES += console/console-config.c
+
# bsp_i2c
libbsp_a_SOURCES += i2c/i2c_init.c
# bsp_spi
diff --git a/c/src/lib/libbsp/powerpc/gen83xx/console/console-config.c b/c/src/lib/libbsp/powerpc/gen83xx/console/console-config.c
index b3ccb9c..8dd7249 100644
--- a/c/src/lib/libbsp/powerpc/gen83xx/console/console-config.c
+++ b/c/src/lib/libbsp/powerpc/gen83xx/console/console-config.c
@@ -5,10 +5,10 @@
*/

/*
- * Copyright (c) 2008, 2010 embedded brains GmbH. All rights reserved.
+ * Copyright (c) 2008-2014 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
- * Obere Lagerstr. 30
+ * Dornierstr. 4
* 82178 Puchheim
* Germany
* <rtems-L1vi/***@public.gmane.org>
@@ -20,104 +20,92 @@

#include <rtems/bspIo.h>

-#include <libchip/serial.h>
#include <libchip/ns16550.h>
-#include "../../../shared/console_private.h"

#include <mpc83xx/mpc83xx.h>

-#include <bspopts.h>
+#include <bsp.h>
#include <bsp/irq.h>
-
-#ifdef BSP_USE_UART2
- #define PORT_COUNT 2
-#else
- #define PORT_COUNT 1
-#endif
+#include <bsp/console-termios.h>

#ifdef BSP_USE_UART_INTERRUPTS
- #define DEVICE_FNS &ns16550_fns
+ #define DEVICE_FNS &ns16550_handler_interrupt
#else
- #define DEVICE_FNS &ns16550_fns_polled
+ #define DEVICE_FNS &ns16550_handler_polled
#endif

-static uint8_t gen83xx_console_get_register(uint32_t addr, uint8_t i)
+static uint8_t gen83xx_console_get_register(uintptr_t addr, uint8_t i)
{
volatile uint8_t *reg = (volatile uint8_t *) addr;

return reg [i];
}

-static void gen83xx_console_set_register(uint32_t addr, uint8_t i, uint8_t val)
+static void gen83xx_console_set_register(uintptr_t addr, uint8_t i, uint8_t val)
{
volatile uint8_t *reg = (volatile uint8_t *) addr;

- reg [i] = val;
+ reg [i] = val;
}

-unsigned long Console_Configuration_Count = PORT_COUNT;
-
-console_tbl Console_Configuration_Ports [PORT_COUNT] = {
- {
- .sDeviceName = "/dev/ttyS0",
- .deviceType = SERIAL_NS16550,
- .pDeviceFns = DEVICE_FNS,
- .deviceProbe = NULL,
- .pDeviceFlow = NULL,
- .ulMargin = 16,
- .ulHysteresis = 8,
- .pDeviceParams = (void *) BSP_CONSOLE_BAUD,
- .ulCtrlPort1 = (uint32_t) &mpc83xx.duart [0],
- .ulCtrlPort2 = 0,
- .ulDataPort = (uint32_t) &mpc83xx.duart [0],
- .getRegister = gen83xx_console_get_register,
- .setRegister = gen83xx_console_set_register,
- .getData = NULL,
- .setData = NULL,
- .ulClock = 0,
+static ns16550_context gen83xx_uart_context_0 = {
+ .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 0"),
+ .get_reg = gen83xx_console_get_register,
+ .set_reg = gen83xx_console_set_register,
+ .port = (uintptr_t) &mpc83xx.duart[0],
#if MPC83XX_CHIP_TYPE / 10 == 830
- .ulIntVector = BSP_IPIC_IRQ_UART
+ .irq = BSP_IPIC_IRQ_UART,
#else
- .ulIntVector = BSP_IPIC_IRQ_UART1
+ .irq = BSP_IPIC_IRQ_UART1,
#endif
- }
+ .initial_baud = BSP_CONSOLE_BAUD
+};
+
#ifdef BSP_USE_UART2
- , {
- .sDeviceName = "/dev/ttyS1",
- .deviceType = SERIAL_NS16550,
- .pDeviceFns = DEVICE_FNS,
- .deviceProbe = NULL,
- .pDeviceFlow = NULL,
- .ulMargin = 16,
- .ulHysteresis = 8,
- .pDeviceParams = (void *) BSP_CONSOLE_BAUD,
- .ulCtrlPort1 = (uint32_t) &mpc83xx.duart [1],
- .ulCtrlPort2 = 0,
- .ulDataPort = (uint32_t) &mpc83xx.duart [1],
- .getRegister = gen83xx_console_get_register,
- .setRegister = gen83xx_console_set_register,
- .getData = NULL,
- .setData = NULL,
- .ulClock = 0,
+static ns16550_context gen83xx_uart_context_1 = {
+ .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 1"),
+ .get_reg = gen83xx_console_get_register,
+ .set_reg = gen83xx_console_set_register,
+ .port = (uintptr_t) &mpc83xx.duart[1],
#if MPC83XX_CHIP_TYPE / 10 == 830
- .ulIntVector = BSP_IPIC_IRQ_UART
+ .irq = BSP_IPIC_IRQ_UART,
#else
- .ulIntVector = BSP_IPIC_IRQ_UART2
+ .irq = BSP_IPIC_IRQ_UART2,
#endif
+ .initial_baud = BSP_CONSOLE_BAUD
+};
+#endif
+
+const console_device console_device_table[] = {
+ {
+ .device_file = "/dev/ttyS0",
+ .probe = ns16550_probe,
+ .handler = DEVICE_FNS,
+ .context = &gen83xx_uart_context_0.base
+ }
+#ifdef BSP_USE_UART2
+ , {
+ .device_file = "/dev/ttyS1",
+ .probe = ns16550_probe,
+ .handler = DEVICE_FNS,
+ .context = &gen83xx_uart_context_1.base
}
#endif
};

+const size_t console_device_count = RTEMS_ARRAY_SIZE(console_device_table);
+
static void gen83xx_output_char(char c)
{
- const console_fns *console = Console_Port_Tbl [Console_Port_Minor]->pDeviceFns;
-
+ rtems_termios_device_context *ctx = console_device_table[0].context;
+
if (c == '\n') {
- console->deviceWritePolled((int) Console_Port_Minor, '\r');
+ ns16550_polled_putchar(ctx, '\r');
}
- console->deviceWritePolled((int) Console_Port_Minor, c);
+
+ ns16550_polled_putchar(ctx, c);
}

-BSP_output_char_function_type BSP_output_char = gen83xx_output_char;
+BSP_output_char_function_type BSP_output_char = gen83xx_output_char;

BSP_polling_getchar_function_type BSP_poll_char = NULL;
diff --git a/c/src/lib/libbsp/powerpc/gen83xx/startup/bspstart.c b/c/src/lib/libbsp/powerpc/gen83xx/startup/bspstart.c
index 4428b8d..f1ffcac 100644
--- a/c/src/lib/libbsp/powerpc/gen83xx/startup/bspstart.c
+++ b/c/src/lib/libbsp/powerpc/gen83xx/startup/bspstart.c
@@ -7,12 +7,13 @@
*/

/*
- * Copyright (c) 2008
- * Embedded Brains GmbH
- * Obere Lagerstr. 30
- * D-82178 Puchheim
- * Germany
- * rtems-L1vi/***@public.gmane.org
+ * Copyright (c) 2008-2014 embedded brains GmbH. All rights reserved.
+ *
+ * embedded brains GmbH
+ * Dornierstr. 4
+ * 82178 Puchheim
+ * Germany
+ * <info-L1vi/***@public.gmane.org>
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
@@ -21,7 +22,7 @@

#include <rtems/counter.h>

-#include <libchip/serial.h>
+#include <libchip/ns16550.h>

#include <libcpu/powerpc-utility.h>

@@ -31,6 +32,7 @@
#include <bsp/irq-generic.h>
#include <bsp/linker-symbols.h>
#include <bsp/u-boot.h>
+#include <bsp/console-termios.h>

/* Configuration parameters for console driver, ... */
unsigned int BSP_bus_frequency;
@@ -54,6 +56,7 @@ void BSP_panic(char *s)
rtems_interrupt_level level;

rtems_interrupt_disable(level);
+ (void) level;

printk("%s PANIC %s\n", rtems_get_version_string(), s);

@@ -67,6 +70,7 @@ void _BSP_Fatal_error(unsigned n)
rtems_interrupt_level level;

rtems_interrupt_disable( level);
+ (void) level;

printk( "%s PANIC ERROR %u\n", rtems_get_version_string(), n);

@@ -80,15 +84,12 @@ void bsp_start( void)
rtems_status_code sc = RTEMS_SUCCESSFUL;
unsigned long i = 0;

- ppc_cpu_id_t myCpu;
- ppc_cpu_revision_t myCpuRevision;
-
/*
* Get CPU identification dynamically. Note that the get_ppc_cpu_type() function
* store the result in global variables so that it can be used latter...
*/
- myCpu = get_ppc_cpu_type();
- myCpuRevision = get_ppc_cpu_revision();
+ get_ppc_cpu_type();
+ get_ppc_cpu_revision();

/* Basic CPU initialization */
cpu_init();
@@ -122,12 +123,13 @@ void bsp_start( void)
rtems_counter_initialize_converter(bsp_time_base_frequency);

/* Initialize some console parameters */
- for (i = 0; i < Console_Configuration_Count; ++i) {
- Console_Configuration_Ports [i].ulClock = BSP_bus_frequency;
+ for (i = 0; i < console_device_count; ++i) {
+ ns16550_context *ctx = (ns16550_context *) console_device_table[i].context;
+
+ ctx->clock = BSP_bus_frequency;

#ifdef HAS_UBOOT
- Console_Configuration_Ports [i].pDeviceParams =
- (void *) bsp_uboot_board_info.bi_baudrate;
+ ctx->initial_baud = bsp_uboot_board_info.bi_baudrate;
#endif
}

diff --git a/c/src/lib/libbsp/powerpc/qoriq/Makefile.am b/c/src/lib/libbsp/powerpc/qoriq/Makefile.am
index ebd4160..97d97a2 100644
--- a/c/src/lib/libbsp/powerpc/qoriq/Makefile.am
+++ b/c/src/lib/libbsp/powerpc/qoriq/Makefile.am
@@ -92,15 +92,11 @@ libbsp_a_SOURCES += ../../shared/src/irq-shell.c
libbsp_a_SOURCES += irq/irq.c

# Console
-libbsp_a_SOURCES += ../../shared/console.c \
- ../../shared/console_select.c \
- console/uart-bridge-master.c \
- console/uart-bridge-slave.c \
- console/console-config.c \
- ../../shared/console_read.c \
- ../../shared/console_write.c \
- ../../shared/console_control.c
-
+libbsp_a_SOURCES += ../../shared/console-termios-init.c
+libbsp_a_SOURCES += ../../shared/console-termios.c
+libbsp_a_SOURCES += console/uart-bridge-master.c
+libbsp_a_SOURCES += console/uart-bridge-slave.c
+libbsp_a_SOURCES += console/console-config.c

# RTC
libbsp_a_SOURCES += ../../shared/tod.c \
diff --git a/c/src/lib/libbsp/powerpc/qoriq/console/console-config.c b/c/src/lib/libbsp/powerpc/qoriq/console/console-config.c
index 6260fd3..1abefe8 100644
--- a/c/src/lib/libbsp/powerpc/qoriq/console/console-config.c
+++ b/c/src/lib/libbsp/powerpc/qoriq/console/console-config.c
@@ -7,10 +7,10 @@
*/

/*
- * Copyright (c) 2010 embedded brains GmbH. All rights reserved.
+ * Copyright (c) 2010-2014 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
- * Obere Lagerstr. 30
+ * Dornierstr. 4
* 82178 Puchheim
* Germany
* <rtems-L1vi/***@public.gmane.org>
@@ -20,25 +20,16 @@
* http://www.rtems.org/license/LICENSE.
*/

-#include <assert.h>
-
#include <rtems/bspIo.h>

-#include <libchip/serial.h>
#include <libchip/ns16550.h>
-#include "../../../shared/console_private.h"

-#include <bspopts.h>
+#include <bsp.h>
#include <bsp/irq.h>
#include <bsp/qoriq.h>
#include <bsp/intercom.h>
#include <bsp/uart-bridge.h>
-
-#define CONSOLE_COUNT \
- (QORIQ_UART_0_ENABLE \
- + QORIQ_UART_1_ENABLE \
- + QORIQ_UART_BRIDGE_0_ENABLE \
- + QORIQ_UART_BRIDGE_1_ENABLE)
+#include <bsp/console-termios.h>

#if (QORIQ_UART_0_ENABLE + QORIQ_UART_BRIDGE_0_ENABLE == 2) \
|| (QORIQ_UART_1_ENABLE + QORIQ_UART_BRIDGE_1_ENABLE == 2)
@@ -47,158 +38,156 @@
#define BRIDGE_SLAVE
#endif

+#ifdef BSP_USE_UART_INTERRUPTS
+ #define DEVICE_FNS &ns16550_handler_interrupt
+#else
+ #define DEVICE_FNS &ns16550_handler_polled
+#endif
+
+#if QORIQ_UART_0_ENABLE || QORIQ_UART_1_ENABLE
+ static uint8_t get_register(uintptr_t addr, uint8_t i)
+ {
+ volatile uint8_t *reg = (uint8_t *) addr;
+
+ return reg [i];
+ }
+
+ static void set_register(uintptr_t addr, uint8_t i, uint8_t val)
+ {
+ volatile uint8_t *reg = (uint8_t *) addr;
+
+ reg [i] = val;
+ }
+#endif
+
+#if QORIQ_UART_0_ENABLE
+static ns16550_context qoriq_uart_context_0 = {
+ .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 0"),
+ .get_reg = get_register,
+ .set_reg = set_register,
+ .port = (uintptr_t) &qoriq.uart_0,
+ .irq = QORIQ_IRQ_DUART,
+ .initial_baud = BSP_CONSOLE_BAUD
+};
+#endif
+
+#if QORIQ_UART_1_ENABLE
+static ns16550_context qoriq_uart_context_1 = {
+ .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART 1"),
+ .get_reg = get_register,
+ .set_reg = set_register,
+ .port = (uintptr_t) &qoriq.uart_1,
+ .irq = QORIQ_IRQ_DUART,
+ .initial_baud = BSP_CONSOLE_BAUD
+};
+#endif
+
#ifdef BRIDGE_MASTER
+ #define BRIDGE_PROBE qoriq_uart_bridge_master_probe
#define BRIDGE_FNS &qoriq_uart_bridge_master
#if QORIQ_UART_BRIDGE_0_ENABLE
- static uart_bridge_master_control bridge_0_control = {
+ static uart_bridge_master_context bridge_0_context = {
+ .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART Bridge 0"),
.device_path = "/dev/ttyS0",
.type = INTERCOM_TYPE_UART_0,
.transmit_fifo = RTEMS_CHAIN_INITIALIZER_EMPTY(
- bridge_0_control.transmit_fifo
+ bridge_0_context.transmit_fifo
)
};
- #define BRIDGE_0_CONTROL &bridge_0_control
+ #define BRIDGE_0_CONTEXT &bridge_0_context
#endif
#if QORIQ_UART_BRIDGE_1_ENABLE
- static uart_bridge_master_control bridge_1_control = {
+ static uart_bridge_master_context bridge_1_context = {
+ .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART Bridge 1"),
.device_path = "/dev/ttyS1",
.type = INTERCOM_TYPE_UART_1,
.transmit_fifo = RTEMS_CHAIN_INITIALIZER_EMPTY(
- bridge_1_control.transmit_fifo
+ bridge_1_context.transmit_fifo
)
};
- #define BRIDGE_1_CONTROL &bridge_1_control
+ #define BRIDGE_1_CONTEXT &bridge_1_context
#endif
#endif

#ifdef BRIDGE_SLAVE
+ #define BRIDGE_PROBE console_device_probe_default
#define BRIDGE_FNS &qoriq_uart_bridge_slave
#if QORIQ_UART_BRIDGE_0_ENABLE
- static uart_bridge_slave_control bridge_0_control = {
+ static uart_bridge_slave_context bridge_0_context = {
+ .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART Bridge 0"),
.type = INTERCOM_TYPE_UART_0,
.transmit_fifo = RTEMS_CHAIN_INITIALIZER_EMPTY(
- bridge_0_control.transmit_fifo
+ bridge_0_context.transmit_fifo
)
};
- #define BRIDGE_0_CONTROL &bridge_0_control
+ #define BRIDGE_0_CONTEXT &bridge_0_context
#endif
#if QORIQ_UART_BRIDGE_1_ENABLE
- static uart_bridge_slave_control bridge_1_control = {
+ static uart_bridge_slave_context bridge_1_context = {
+ .base = RTEMS_TERMIOS_DEVICE_CONTEXT_INITIALIZER("UART Bridge 1"),
.type = INTERCOM_TYPE_UART_1,
.transmit_fifo = RTEMS_CHAIN_INITIALIZER_EMPTY(
- bridge_1_control.transmit_fifo
+ bridge_1_context.transmit_fifo
)
};
- #define BRIDGE_1_CONTROL &bridge_1_control
+ #define BRIDGE_1_CONTEXT &bridge_1_context
#endif
#endif

-#ifdef BSP_USE_UART_INTERRUPTS
- #define DEVICE_FNS &ns16550_fns
-#else
- #define DEVICE_FNS &ns16550_fns_polled
-#endif
-
-#if QORIQ_UART_0_ENABLE || QORIQ_UART_1_ENABLE
- static uint8_t get_register(uintptr_t addr, uint8_t i)
- {
- volatile uint8_t *reg = (uint8_t *) addr;
-
- return reg [i];
- }
-
- static void set_register(uintptr_t addr, uint8_t i, uint8_t val)
- {
- volatile uint8_t *reg = (uint8_t *) addr;
-
- reg [i] = val;
- }
-#endif
-
-unsigned long Console_Configuration_Count = CONSOLE_COUNT;
-console_tbl Console_Configuration_Ports [CONSOLE_COUNT] = {
+const console_device console_device_table[] = {
#if QORIQ_UART_0_ENABLE
{
- .sDeviceName = "/dev/ttyS0",
- .deviceType = SERIAL_NS16550,
- .pDeviceFns = DEVICE_FNS,
- .deviceProbe = NULL,
- .pDeviceFlow = NULL,
- .ulMargin = 16,
- .ulHysteresis = 8,
- .pDeviceParams = (void *) BSP_CONSOLE_BAUD,
- .ulCtrlPort1 = (uintptr_t) &qoriq.uart_0,
- .ulCtrlPort2 = 0,
- .ulDataPort = (uintptr_t) &qoriq.uart_0,
- .getRegister = get_register,
- .setRegister = set_register,
- .getData = NULL,
- .setData = NULL,
- .ulClock = 0,
- .ulIntVector = QORIQ_IRQ_DUART
+ .device_file = "/dev/ttyS0",
+ .probe = ns16550_probe,
+ .handler = DEVICE_FNS,
+ .context = &qoriq_uart_context_0.base
},
#endif
#if QORIQ_UART_1_ENABLE
{
- .sDeviceName = "/dev/ttyS1",
- .deviceType = SERIAL_NS16550,
- .pDeviceFns = DEVICE_FNS,
- .deviceProbe = NULL,
- .pDeviceFlow = NULL,
- .ulMargin = 16,
- .ulHysteresis = 8,
- .pDeviceParams = (void *) BSP_CONSOLE_BAUD,
- .ulCtrlPort1 = (uintptr_t) &qoriq.uart_1,
- .ulCtrlPort2 = 0,
- .ulDataPort = (uintptr_t) &qoriq.uart_1,
- .getRegister = get_register,
- .setRegister = set_register,
- .getData = NULL,
- .setData = NULL,
- .ulClock = 0,
- .ulIntVector = QORIQ_IRQ_DUART
+ .device_file = "/dev/ttyS1",
+ .probe = ns16550_probe,
+ .handler = DEVICE_FNS,
+ .context = &qoriq_uart_context_1.base
},
#endif
#if QORIQ_UART_BRIDGE_0_ENABLE
{
#if QORIQ_UART_1_ENABLE
- .sDeviceName = "/dev/ttyB0",
+ .device_file = "/dev/ttyB0",
#else
- .sDeviceName = "/dev/ttyS0",
+ .device_file = "/dev/ttyS0",
#endif
- .deviceType = SERIAL_CUSTOM,
- .pDeviceFns = BRIDGE_FNS,
- .pDeviceParams = BRIDGE_0_CONTROL
+ .probe = BRIDGE_PROBE,
+ .handler = BRIDGE_FNS,
+ .context = BRIDGE_0_CONTEXT
},
#endif
#if QORIQ_UART_BRIDGE_1_ENABLE
{
#if QORIQ_UART_1_ENABLE
- .sDeviceName = "/dev/ttyB1",
+ .device_file = "/dev/ttyB1",
#else
- .sDeviceName = "/dev/ttyS1",
+ .device_file = "/dev/ttyS1",
#endif
- .deviceType = SERIAL_CUSTOM,
- .pDeviceFns = BRIDGE_FNS,
- .pDeviceParams = BRIDGE_1_CONTROL
+ .probe = BRIDGE_PROBE,
+ .handler = BRIDGE_FNS,
+ .context = BRIDGE_1_CONTEXT
}
#endif
};

+const size_t console_device_count = RTEMS_ARRAY_SIZE(console_device_table);
+
static void output_char(char c)
{
- int minor = (int) Console_Port_Minor;
- const console_tbl **ct_tbl = Console_Port_Tbl;
-
- if (ct_tbl != NULL) {
- const console_fns *cf = ct_tbl[minor]->pDeviceFns;
+ rtems_termios_device_context *ctx = console_device_table[0].context;

- if (c == '\n') {
- (*cf->deviceWritePolled)(minor, '\r');
- }
-
- (*cf->deviceWritePolled)(minor, c);
+ if (c == '\n') {
+ ns16550_polled_putchar(ctx, '\r');
}
+
+ ns16550_polled_putchar(ctx, c);
}

BSP_output_char_function_type BSP_output_char = output_char;
diff --git a/c/src/lib/libbsp/powerpc/qoriq/console/uart-bridge-master.c b/c/src/lib/libbsp/powerpc/qoriq/console/uart-bridge-master.c
index 939448a..41ad517 100644
--- a/c/src/lib/libbsp/powerpc/qoriq/console/uart-bridge-master.c
+++ b/c/src/lib/libbsp/powerpc/qoriq/console/uart-bridge-master.c
@@ -7,10 +7,10 @@
*/

/*
- * Copyright (c) 2011 embedded brains GmbH. All rights reserved.
+ * Copyright (c) 2011-2014 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
- * Obere Lagerstr. 30
+ * Dornierstr. 4
* 82178 Puchheim
* Germany
* <rtems-L1vi/***@public.gmane.org>
@@ -26,8 +26,6 @@
#include <unistd.h>
#include <termios.h>

-#include <libchip/sersupp.h>
-
#include <bspopts.h>
#include <bsp/uart-bridge.h>

@@ -55,12 +53,12 @@ static void serial_settings(int fd)
static void uart_bridge_master_service(intercom_packet *packet, void *arg)
{
rtems_status_code sc = RTEMS_SUCCESSFUL;
- uart_bridge_master_control *control = arg;
+ uart_bridge_master_context *ctx = arg;

sc = rtems_chain_append_with_notification(
- &control->transmit_fifo,
+ &ctx->transmit_fifo,
&packet->glue.node,
- control->transmit_task,
+ ctx->transmit_task,
TRANSMIT_EVENT
);
assert(sc == RTEMS_SUCCESSFUL);
@@ -68,10 +66,10 @@ static void uart_bridge_master_service(intercom_packet *packet, void *arg)

static void receive_task(rtems_task_argument arg)
{
- uart_bridge_master_control *control = (uart_bridge_master_control *) arg;
- intercom_type type = control->type;
+ uart_bridge_master_context *ctx = (uart_bridge_master_context *) arg;
+ intercom_type type = ctx->type;

- int fd = open(control->device_path, O_RDONLY);
+ int fd = open(ctx->device_path, O_RDONLY);
assert(fd >= 0);

serial_settings(fd);
@@ -94,10 +92,10 @@ static void receive_task(rtems_task_argument arg)
static void transmit_task(rtems_task_argument arg)
{
rtems_status_code sc = RTEMS_SUCCESSFUL;
- uart_bridge_master_control *control = (uart_bridge_master_control *) arg;
- rtems_chain_control *fifo = &control->transmit_fifo;
+ uart_bridge_master_context *ctx = (uart_bridge_master_context *) arg;
+ rtems_chain_control *fifo = &ctx->transmit_fifo;

- int fd = open(control->device_path, O_WRONLY);
+ int fd = open(ctx->device_path, O_WRONLY);
assert(fd >= 0);

serial_settings(fd);
@@ -119,12 +117,12 @@ static void transmit_task(rtems_task_argument arg)
static rtems_id create_task(
char name,
rtems_task_entry entry,
- uart_bridge_master_control *control
+ uart_bridge_master_context *ctx
)
{
rtems_status_code sc = RTEMS_SUCCESSFUL;
rtems_id task = RTEMS_ID_NONE;
- char index = (char) ('0' + control->type - INTERCOM_TYPE_UART_0);
+ char index = (char) ('0' + ctx->type - INTERCOM_TYPE_UART_0);

sc = rtems_task_create(
rtems_build_name('U', 'B', name, index),
@@ -139,57 +137,45 @@ static rtems_id create_task(
sc = rtems_task_start(
task,
entry,
- (rtems_task_argument) control
+ (rtems_task_argument) ctx
);
assert(sc == RTEMS_SUCCESSFUL);

return task;
}

-static void initialize(int minor)
+bool qoriq_uart_bridge_master_probe(rtems_termios_device_context *base)
{
- console_tbl *ct = Console_Port_Tbl [minor];
- uart_bridge_master_control *control = ct->pDeviceParams;
- intercom_type type = control->type;
-
- qoriq_intercom_service_install(type, uart_bridge_master_service, control);
- create_task('R', receive_task, control);
- control->transmit_task = create_task('T', transmit_task, control);
-}
+ uart_bridge_master_context *ctx = (uart_bridge_master_context *) base;
+ intercom_type type = ctx->type;

-static int first_open(int major, int minor, void *arg)
-{
- return -1;
-}
+ qoriq_intercom_service_install(type, uart_bridge_master_service, ctx);
+ create_task('R', receive_task, ctx);
+ ctx->transmit_task = create_task('T', transmit_task, ctx);

-static int last_close(int major, int minor, void *arg)
-{
- return -1;
+ return true;
}

-static int read_polled(int minor)
-{
- return -1;
-}
-
-static void write_polled(int minor, char c)
+static bool first_open(
+ struct rtems_termios_tty *tty,
+ rtems_termios_device_context *base,
+ struct termios *term,
+ rtems_libio_open_close_args_t *args
+)
{
- /* Do nothing */
+ return false;
}

-static int set_attributes(int minor, const struct termios *term)
+static bool set_attributes(
+ rtems_termios_device_context *base,
+ const struct termios *term
+)
{
- return -1;
+ return false;
}

-const console_fns qoriq_uart_bridge_master = {
- .deviceProbe = libchip_serial_default_probe,
- .deviceFirstOpen = first_open,
- .deviceLastClose = last_close,
- .deviceRead = read_polled,
- .deviceWrite = NULL,
- .deviceInitialize = initialize,
- .deviceWritePolled = write_polled,
- .deviceSetAttributes = set_attributes,
- .deviceOutputUsesInterrupts = false
+const rtems_termios_device_handler qoriq_uart_bridge_master = {
+ .first_open = first_open,
+ .set_attributes = set_attributes,
+ .mode = TERMIOS_POLLED
};
diff --git a/c/src/lib/libbsp/powerpc/qoriq/console/uart-bridge-slave.c b/c/src/lib/libbsp/powerpc/qoriq/console/uart-bridge-slave.c
index 71969e3..44d4cfb 100644
--- a/c/src/lib/libbsp/powerpc/qoriq/console/uart-bridge-slave.c
+++ b/c/src/lib/libbsp/powerpc/qoriq/console/uart-bridge-slave.c
@@ -50,8 +50,8 @@ static void restore_preemption(rtems_mode prev_mode)

static void uart_bridge_slave_service(intercom_packet *packet, void *arg)
{
- uart_bridge_slave_control *control = arg;
- struct rtems_termios_tty *tty = control->tty;
+ uart_bridge_slave_context *ctx = arg;
+ struct rtems_termios_tty *tty = ctx->tty;

/* Workaround for https://www.rtems.org/bugzilla/show_bug.cgi?id=1736 */
rtems_mode prev_mode = disable_preemption();
@@ -65,9 +65,9 @@ static void uart_bridge_slave_service(intercom_packet *packet, void *arg)
static void transmit_task(rtems_task_argument arg)
{
rtems_status_code sc = RTEMS_SUCCESSFUL;
- uart_bridge_slave_control *control = (uart_bridge_slave_control *) arg;
- rtems_chain_control *fifo = &control->transmit_fifo;
- struct rtems_termios_tty *tty = control->tty;
+ uart_bridge_slave_context *ctx = (uart_bridge_slave_context *) arg;
+ rtems_chain_control *fifo = &ctx->transmit_fifo;
+ struct rtems_termios_tty *tty = ctx->tty;

while (true) {
intercom_packet *packet = NULL;
@@ -91,12 +91,12 @@ static void transmit_task(rtems_task_argument arg)
}

static void create_transmit_task(
- uart_bridge_slave_control *control
+ uart_bridge_slave_context *ctx
)
{
rtems_status_code sc = RTEMS_SUCCESSFUL;
rtems_id task = RTEMS_ID_NONE;
- char index = (char) ('0' + control->type - INTERCOM_TYPE_UART_0);
+ char index = (char) ('0' + ctx->type - INTERCOM_TYPE_UART_0);

sc = rtems_task_create(
rtems_build_name('U', 'B', 'T', index),
@@ -111,54 +111,53 @@ static void create_transmit_task(
sc = rtems_task_start(
task,
transmit_task,
- (rtems_task_argument) control
+ (rtems_task_argument) ctx
);
assert(sc == RTEMS_SUCCESSFUL);

- control->transmit_task = task;
+ ctx->transmit_task = task;
}

-static void initialize(int minor)
+static bool first_open(
+ struct rtems_termios_tty *tty,
+ rtems_termios_device_context *base,
+ struct termios *term,
+ rtems_libio_open_close_args_t *args
+)
{
- /* Do nothing */
-}
+ uart_bridge_slave_context *ctx = (uart_bridge_slave_context *) base;
+ intercom_type type = ctx->type;

-static int first_open(int major, int minor, void *arg)
-{
- rtems_libio_open_close_args_t *oc = (rtems_libio_open_close_args_t *) arg;
- struct rtems_termios_tty *tty = (struct rtems_termios_tty *) oc->iop->data1;
- console_tbl *ct = Console_Port_Tbl[minor];
- console_data *cd = &Console_Port_Data [minor];
- uart_bridge_slave_control *control = ct->pDeviceParams;
- intercom_type type = control->type;
-
- control->tty = tty;
- cd->termios_data = tty;
+ ctx->tty = tty;
rtems_termios_set_initial_baud(tty, 115200);
- create_transmit_task(control);
- qoriq_intercom_service_install(type, uart_bridge_slave_service, control);
+ create_transmit_task(ctx);
+ qoriq_intercom_service_install(type, uart_bridge_slave_service, ctx);

- return 0;
+ return true;
}

-static int last_close(int major, int minor, void *arg)
+static void last_close(
+ struct rtems_termios_tty *tty,
+ rtems_termios_device_context *base,
+ rtems_libio_open_close_args_t *args
+)
{
- console_tbl *ct = Console_Port_Tbl[minor];
- uart_bridge_slave_control *control = ct->pDeviceParams;
-
- qoriq_intercom_service_remove(control->type);
+ uart_bridge_slave_context *ctx = (uart_bridge_slave_context *) base;

- return 0;
+ qoriq_intercom_service_remove(ctx->type);
}

-static ssize_t write_with_interrupts(int minor, const char *buf, size_t len)
+static void write_with_interrupts(
+ rtems_termios_device_context *base,
+ const char *buf,
+ size_t len
+)
{
if (len > 0) {
rtems_status_code sc = RTEMS_SUCCESSFUL;
- console_tbl *ct = Console_Port_Tbl[minor];
- uart_bridge_slave_control *control = ct->pDeviceParams;
+ uart_bridge_slave_context *ctx = (uart_bridge_slave_context *) base;
intercom_packet *packet = qoriq_intercom_allocate_packet(
- control->type,
+ ctx->type,
INTERCOM_SIZE_64
);

@@ -170,44 +169,27 @@ static ssize_t write_with_interrupts(int minor, const char *buf, size_t len)
* another context.
*/
sc = rtems_chain_append_with_notification(
- &control->transmit_fifo,
+ &ctx->transmit_fifo,
&packet->glue.node,
- control->transmit_task,
+ ctx->transmit_task,
TRANSMIT_EVENT
);
assert(sc == RTEMS_SUCCESSFUL);
}
-
- return 0;
-}
-
-static void write_polled(int minor, char c)
-{
- console_tbl *ct = Console_Port_Tbl[minor];
- uart_bridge_slave_control *control = ct->pDeviceParams;
- intercom_packet *packet = qoriq_intercom_allocate_packet(
- control->type,
- INTERCOM_SIZE_64
- );
- char *data = packet->data;
- data [0] = c;
- packet->size = 1;
- qoriq_intercom_send_packet(QORIQ_UART_BRIDGE_MASTER_CORE, packet);
}

-static int set_attribues(int minor, const struct termios *term)
+static bool set_attributes(
+ rtems_termios_device_context *base,
+ const struct termios *term
+)
{
- return -1;
+ return false;
}

-const console_fns qoriq_uart_bridge_slave = {
- .deviceProbe = libchip_serial_default_probe,
- .deviceFirstOpen = first_open,
- .deviceLastClose = last_close,
- .deviceRead = NULL,
- .deviceWrite = write_with_interrupts,
- .deviceInitialize = initialize,
- .deviceWritePolled = write_polled,
- .deviceSetAttributes = set_attribues,
- .deviceOutputUsesInterrupts = true
+const rtems_termios_device_handler qoriq_uart_bridge_slave = {
+ .first_open = first_open,
+ .last_close = last_close,
+ .write = write_with_interrupts,
+ .set_attributes = set_attributes,
+ .mode = TERMIOS_IRQ_DRIVEN
};
diff --git a/c/src/lib/libbsp/powerpc/qoriq/include/uart-bridge.h b/c/src/lib/libbsp/powerpc/qoriq/include/uart-bridge.h
index e94fe20..cd342ff 100644
--- a/c/src/lib/libbsp/powerpc/qoriq/include/uart-bridge.h
+++ b/c/src/lib/libbsp/powerpc/qoriq/include/uart-bridge.h
@@ -7,10 +7,10 @@
*/

/*
- * Copyright (c) 2011 embedded brains GmbH. All rights reserved.
+ * Copyright (c) 2011-2014 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
- * Obere Lagerstr. 30
+ * Dornierstr. 4
* 82178 Puchheim
* Germany
* <rtems-L1vi/***@public.gmane.org>
@@ -23,7 +23,7 @@
#ifndef LIBBSP_POWERPC_QORIQ_UART_BRIDGE_H
#define LIBBSP_POWERPC_QORIQ_UART_BRIDGE_H

-#include <libchip/serial.h>
+#include <rtems/termiostypes.h>

#include <bsp/intercom.h>

@@ -42,22 +42,26 @@ extern "C" {
*/

typedef struct {
+ rtems_termios_device_context base;
const char *device_path;
intercom_type type;
rtems_id transmit_task;
rtems_chain_control transmit_fifo;
-} uart_bridge_master_control;
+} uart_bridge_master_context;

typedef struct {
+ rtems_termios_device_context base;
struct rtems_termios_tty *tty;
intercom_type type;
rtems_id transmit_task;
rtems_chain_control transmit_fifo;
-} uart_bridge_slave_control;
+} uart_bridge_slave_context;

-extern const console_fns qoriq_uart_bridge_master;
+bool qoriq_uart_bridge_master_probe(rtems_termios_device_context *base);

-extern const console_fns qoriq_uart_bridge_slave;
+extern const rtems_termios_device_handler qoriq_uart_bridge_master;
+
+extern const rtems_termios_device_handler qoriq_uart_bridge_slave;

/** @} */

diff --git a/c/src/lib/libbsp/powerpc/qoriq/startup/bspstart.c b/c/src/lib/libbsp/powerpc/qoriq/startup/bspstart.c
index 5785078..43caabb 100644
--- a/c/src/lib/libbsp/powerpc/qoriq/startup/bspstart.c
+++ b/c/src/lib/libbsp/powerpc/qoriq/startup/bspstart.c
@@ -24,7 +24,7 @@
#include <rtems/config.h>
#include <rtems/counter.h>

-#include <libchip/serial.h>
+#include <libchip/ns16550.h>

#include <libcpu/powerpc-utility.h>

@@ -36,6 +36,7 @@
#include <bsp/linker-symbols.h>
#include <bsp/mmu.h>
#include <bsp/qoriq.h>
+#include <bsp/console-termios.h>

LINKER_SYMBOL(bsp_exc_vector_base);

@@ -50,6 +51,7 @@ void BSP_panic(char *s)
rtems_interrupt_level level;

rtems_interrupt_disable(level);
+ (void) level;

printk("%s PANIC %s\n", rtems_get_version_string(), s);

@@ -63,6 +65,7 @@ void _BSP_Fatal_error(unsigned n)
rtems_interrupt_level level;

rtems_interrupt_disable(level);
+ (void) level;

printk("%s PANIC ERROR %u\n", rtems_get_version_string(), n);

@@ -75,15 +78,12 @@ void bsp_start(void)
{
unsigned long i = 0;

- ppc_cpu_id_t myCpu;
- ppc_cpu_revision_t myCpuRevision;
-
/*
* Get CPU identification dynamically. Note that the get_ppc_cpu_type() function
* store the result in global variables so that it can be used latter...
*/
- myCpu = get_ppc_cpu_type();
- myCpuRevision = get_ppc_cpu_revision();
+ get_ppc_cpu_type();
+ get_ppc_cpu_revision();

/* Initialize some device driver parameters */
#ifdef HAS_UBOOT
@@ -93,16 +93,24 @@ void bsp_start(void)
rtems_counter_initialize_converter(BSP_bus_frequency / 8);

/* Initialize some console parameters */
- for (i = 0; i < Console_Configuration_Count; ++i) {
- console_tbl *ct = &Console_Configuration_Ports[i];
-
- ct->ulClock = BSP_bus_frequency;
-
- #ifdef HAS_UBOOT
- if (ct->deviceType == SERIAL_NS16550) {
- ct->pDeviceParams = (void *) bsp_uboot_board_info.bi_baudrate;
- }
- #endif
+ for (i = 0; i < console_device_count; ++i) {
+ const console_device *dev = &console_device_table[i];
+ const rtems_termios_device_handler *ns16550 =
+ #ifdef BSP_USE_UART_INTERRUPTS
+ &ns16550_handler_interrupt;
+ #else
+ &ns16550_handler_polled;
+ #endif
+
+ if (dev->handler == ns16550) {
+ ns16550_context *ctx = (ns16550_context *) dev->context;
+
+ ctx->clock = BSP_bus_frequency;
+
+ #ifdef HAS_UBOOT
+ ctx->initial_baud = bsp_uboot_board_info.bi_baudrate;
+ #endif
+ }
}

/* Disable decrementer */
diff --git a/c/src/libchip/Makefile.am b/c/src/libchip/Makefile.am
index 003c3c1..904561f 100644
--- a/c/src/libchip/Makefile.am
+++ b/c/src/libchip/Makefile.am
@@ -110,6 +110,7 @@ libserialio_a_SOURCES = serial/mc68681.c serial/mc68681_baud.c \
serial/mc68681_reg8.c serial/ns16550.c serial/z85c30.c \
serial/z85c30_reg.c serial/serprobe.c serial/mc68681_p.h \
serial/z85c30_p.h
+libserialio_a_SOURCES += serial/ns16550-context.c

EXTRA_DIST += serial/README.mc68681 serial/README.ns16550 \
serial/README.xr88681 serial/README.z85c30 serial/STATUS
diff --git a/c/src/libchip/serial/ns16550-context.c b/c/src/libchip/serial/ns16550-context.c
new file mode 100644
index 0000000..a812271
--- /dev/null
+++ b/c/src/libchip/serial/ns16550-context.c
@@ -0,0 +1,677 @@
+/**
+ * @file
+ *
+ * This file contains the TTY driver for the National Semiconductor NS16550.
+ *
+ * This part is widely cloned and second sourced. It is found in a number
+ * of "Super IO" controllers.
+ *
+ * This driver uses the termios pseudo driver.
+ */
+
+/*
+ * COPYRIGHT (c) 1998 by Radstone Technology
+ *
+ * THIS FILE IS PROVIDED TO YOU, THE USER, "AS IS", WITHOUT WARRANTY OF ANY
+ * KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTY OF FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK
+ * AS TO THE QUALITY AND PERFORMANCE OF ALL CODE IN THIS FILE IS WITH YOU.
+ *
+ * You are hereby granted permission to use, copy, modify, and distribute
+ * this file, provided that this notice, plus the above copyright notice
+ * and disclaimer, appears in all copies. Radstone Technology will provide
+ * no support for this code.
+ *
+ * COPYRIGHT (c) 1989-2012.
+ * On-Line Applications Research Corporation (OAR).
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#include <stdlib.h>
+
+#include <rtems/bspIo.h>
+
+#include <bsp.h>
+
+#include "ns16550.h"
+#include "ns16550_p.h"
+
+#if defined(BSP_FEATURE_IRQ_EXTENSION)
+ #include <bsp/irq.h>
+#elif defined(BSP_FEATURE_IRQ_LEGACY)
+ #include <bsp/irq.h>
+#elif defined(__PPC__) || defined(__i386__)
+ #include <bsp/irq.h>
+ #define BSP_FEATURE_IRQ_LEGACY
+ #ifdef BSP_SHARED_HANDLER_SUPPORT
+ #define BSP_FEATURE_IRQ_LEGACY_SHARED_HANDLER_SUPPORT
+ #endif
+#endif
+
+static uint32_t NS16550_GetBaudDivisor(ns16550_context *ctx, uint32_t baud)
+{
+ uint32_t clock = ctx->clock;
+ uint32_t baudDivisor = (clock != 0 ? clock : 115200) / (baud * 16);
+
+ if (ctx->has_fractional_divider_register) {
+ uint32_t fractionalDivider = 0x10;
+ uint32_t err = baud;
+ uint32_t mulVal;
+ uint32_t divAddVal;
+
+ clock /= 16 * baudDivisor;
+ for (mulVal = 1; mulVal < 16; ++mulVal) {
+ for (divAddVal = 0; divAddVal < mulVal; ++divAddVal) {
+ uint32_t actual = (mulVal * clock) / (mulVal + divAddVal);
+ uint32_t newErr = actual > baud ? actual - baud : baud - actual;
+
+ if (newErr < err) {
+ err = newErr;
+ fractionalDivider = (mulVal << 4) | divAddVal;
+ }
+ }
+ }
+
+ (*ctx->set_reg)(
+ ctx->port,
+ NS16550_FRACTIONAL_DIVIDER,
+ fractionalDivider
+ );
+ }
+
+ return baudDivisor;
+}
+
+/*
+ * ns16550_enable_interrupts
+ *
+ * This routine initializes the port to have the specified interrupts masked.
+ */
+static void ns16550_enable_interrupts(
+ ns16550_context *ctx,
+ int mask
+)
+{
+ (*ctx->set_reg)(ctx->port, NS16550_INTERRUPT_ENABLE, mask);
+}
+
+/*
+ * ns16550_probe
+ */
+
+bool ns16550_probe(rtems_termios_device_context *base)
+{
+ ns16550_context *ctx = (ns16550_context *) base;
+ uintptr_t pNS16550;
+ uint8_t ucDataByte;
+ uint32_t ulBaudDivisor;
+ ns16550_set_reg setReg;
+ ns16550_get_reg getReg;
+
+ ctx->modem_control = SP_MODEM_IRQ;
+
+ pNS16550 = ctx->port;
+ setReg = ctx->set_reg;
+ getReg = ctx->get_reg;
+
+ /* Clear the divisor latch, clear all interrupt enables,
+ * and reset and
+ * disable the FIFO's.
+ */
+
+ (*setReg)(pNS16550, NS16550_LINE_CONTROL, 0x0);
+ ns16550_enable_interrupts(ctx, NS16550_DISABLE_ALL_INTR );
+
+ /* Set the divisor latch and set the baud rate. */
+
+ ulBaudDivisor = NS16550_GetBaudDivisor(ctx, ctx->initial_baud);
+ ucDataByte = SP_LINE_DLAB;
+ (*setReg)(pNS16550, NS16550_LINE_CONTROL, ucDataByte);
+
+ /* XXX */
+ (*setReg)(pNS16550,NS16550_TRANSMIT_BUFFER,(uint8_t)(ulBaudDivisor & 0xffU));
+ (*setReg)(
+ pNS16550,NS16550_INTERRUPT_ENABLE,
+ (uint8_t)(( ulBaudDivisor >> 8 ) & 0xffU )
+ );
+
+ /* Clear the divisor latch and set the character size to eight bits */
+ /* with one stop bit and no parity checking. */
+ ucDataByte = EIGHT_BITS;
+ (*setReg)(pNS16550, NS16550_LINE_CONTROL, ucDataByte);
+
+ /* Enable and reset transmit and receive FIFOs. TJA */
+ ucDataByte = SP_FIFO_ENABLE;
+ (*setReg)(pNS16550, NS16550_FIFO_CONTROL, ucDataByte);
+
+ ucDataByte = SP_FIFO_ENABLE | SP_FIFO_RXRST | SP_FIFO_TXRST;
+ (*setReg)(pNS16550, NS16550_FIFO_CONTROL, ucDataByte);
+
+ ns16550_enable_interrupts(ctx, NS16550_DISABLE_ALL_INTR);
+
+ /* Set data terminal ready. */
+ /* And open interrupt tristate line */
+ (*setReg)(pNS16550, NS16550_MODEM_CONTROL,ctx->modem_control);
+
+ (*getReg)(pNS16550, NS16550_LINE_STATUS );
+ (*getReg)(pNS16550, NS16550_RECEIVE_BUFFER );
+
+ return true;
+}
+
+#if defined(BSP_FEATURE_IRQ_EXTENSION) || defined(BSP_FEATURE_IRQ_LEGACY)
+
+/**
+ * @brief Process interrupt.
+ */
+static void ns16550_isr(void *arg)
+{
+ rtems_termios_tty *tty = arg;
+ ns16550_context *ctx = rtems_termios_get_device_context(tty);
+ uint32_t port = ctx->port;
+ ns16550_get_reg get = ctx->get_reg;
+ int i = 0;
+ char buf [SP_FIFO_SIZE];
+
+ /* Iterate until no more interrupts are pending */
+ do {
+ /* Fetch received characters */
+ for (i = 0; i < SP_FIFO_SIZE; ++i) {
+ if ((get( port, NS16550_LINE_STATUS) & SP_LSR_RDY) != 0) {
+ buf [i] = (char) get(port, NS16550_RECEIVE_BUFFER);
+ } else {
+ break;
+ }
+ }
+
+ /* Enqueue fetched characters */
+ rtems_termios_enqueue_raw_characters(tty, buf, i);
+
+ /* Check if we can dequeue transmitted characters */
+ if (ctx->transmit_fifo_chars > 0
+ && (get( port, NS16550_LINE_STATUS) & SP_LSR_THOLD) != 0) {
+
+ /* Dequeue transmitted characters */
+ rtems_termios_dequeue_characters(
+ tty,
+ ctx->transmit_fifo_chars
+ );
+ }
+ } while ((get( port, NS16550_INTERRUPT_ID) & SP_IID_0) == 0);
+}
+#endif
+
+/*
+ * ns16550_initialize_interrupts
+ *
+ * This routine initializes the port to operate in interrupt driver mode.
+ */
+static void ns16550_initialize_interrupts(
+ struct rtems_termios_tty *tty,
+ ns16550_context *ctx
+)
+{
+ #ifdef BSP_FEATURE_IRQ_EXTENSION
+ {
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ sc = rtems_interrupt_handler_install(
+ ctx->irq,
+ "NS16550",
+ RTEMS_INTERRUPT_SHARED,
+ ns16550_isr,
+ tty
+ );
+ if (sc != RTEMS_SUCCESSFUL) {
+ /* FIXME */
+ printk( "%s: Error: Install interrupt handler\n", __func__);
+ rtems_fatal_error_occurred( 0xdeadbeef);
+ }
+ }
+ #elif defined(BSP_FEATURE_IRQ_LEGACY)
+ {
+ int rv = 0;
+ #ifdef BSP_FEATURE_IRQ_LEGACY_SHARED_HANDLER_SUPPORT
+ rtems_irq_connect_data cd = {
+ ctx->irq,
+ ns16550_isr,
+ tty,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ };
+ rv = BSP_install_rtems_shared_irq_handler( &cd);
+ #else
+ rtems_irq_connect_data cd = {
+ ctx->irq,
+ ns16550_isr,
+ tty,
+ NULL,
+ NULL,
+ NULL
+ };
+ rv = BSP_install_rtems_irq_handler( &cd);
+ #endif
+ if (rv == 0) {
+ /* FIXME */
+ printk( "%s: Error: Install interrupt handler\n", __func__);
+ rtems_fatal_error_occurred( 0xdeadbeef);
+ }
+ }
+ #endif
+}
+
+/*
+ * ns16550_open
+ */
+
+static bool ns16550_open(
+ struct rtems_termios_tty *tty,
+ rtems_termios_device_context *base,
+ struct termios *term,
+ rtems_libio_open_close_args_t *args
+)
+{
+ ns16550_context *ctx = (ns16550_context *) base;
+
+ /* Set initial baud */
+ rtems_termios_set_initial_baud(tty, ctx->initial_baud);
+
+ if (tty->handler.mode == TERMIOS_IRQ_DRIVEN) {
+ ns16550_initialize_interrupts(tty, ctx);
+ ns16550_enable_interrupts(ctx, NS16550_ENABLE_ALL_INTR_EXCEPT_TX);
+ }
+
+ return true;
+}
+
+static void ns16550_cleanup_interrupts(
+ struct rtems_termios_tty *tty,
+ ns16550_context *ctx
+)
+{
+ #if defined(BSP_FEATURE_IRQ_EXTENSION)
+ rtems_status_code sc = RTEMS_SUCCESSFUL;
+ sc = rtems_interrupt_handler_remove(
+ ctx->irq,
+ ns16550_isr,
+ tty
+ );
+ if (sc != RTEMS_SUCCESSFUL) {
+ /* FIXME */
+ printk("%s: Error: Remove interrupt handler\n", __func__);
+ rtems_fatal_error_occurred(0xdeadbeef);
+ }
+ #elif defined(BSP_FEATURE_IRQ_LEGACY)
+ int rv = 0;
+ rtems_irq_connect_data cd = {
+ .name = ctx->irq,
+ .hdl = ns16550_isr,
+ .handle = tty
+ };
+ rv = BSP_remove_rtems_irq_handler(&cd);
+ if (rv == 0) {
+ /* FIXME */
+ printk("%s: Error: Remove interrupt handler\n", __func__);
+ rtems_fatal_error_occurred(0xdeadbeef);
+ }
+ #endif
+}
+
+/*
+ * ns16550_close
+ */
+
+static void ns16550_close(
+ struct rtems_termios_tty *tty,
+ rtems_termios_device_context *base,
+ rtems_libio_open_close_args_t *args
+)
+{
+ ns16550_context *ctx = (ns16550_context *) base;
+
+ ns16550_enable_interrupts(ctx, NS16550_DISABLE_ALL_INTR);
+
+ if (tty->handler.mode == TERMIOS_IRQ_DRIVEN) {
+ ns16550_cleanup_interrupts(tty, ctx);
+ }
+}
+
+/**
+ * @brief Polled write for NS16550.
+ */
+void ns16550_polled_putchar(rtems_termios_device_context *base, char out)
+{
+ ns16550_context *ctx = (ns16550_context *) base;
+ uintptr_t port = ctx->port;
+ ns16550_get_reg get = ctx->get_reg;
+ ns16550_set_reg set = ctx->set_reg;
+ uint32_t status = 0;
+ rtems_interrupt_lock_context lock_context;
+
+ /* Save port interrupt mask */
+ uint32_t interrupt_mask = get( port, NS16550_INTERRUPT_ENABLE);
+
+ /* Disable port interrupts */
+ ns16550_enable_interrupts(ctx, NS16550_DISABLE_ALL_INTR);
+
+ while (true) {
+ /* Try to transmit the character in a critical section */
+ rtems_termios_device_lock_acquire(&ctx->base, &lock_context);
+
+ /* Read the transmitter holding register and check it */
+ status = get( port, NS16550_LINE_STATUS);
+ if ((status & SP_LSR_THOLD) != 0) {
+ /* Transmit character */
+ set( port, NS16550_TRANSMIT_BUFFER, out);
+
+ /* Finished */
+ rtems_termios_device_lock_release(&ctx->base, &lock_context);
+ break;
+ } else {
+ rtems_termios_device_lock_release(&ctx->base, &lock_context);
+ }
+
+ /* Wait for transmitter holding register to be empty */
+ do {
+ status = get( port, NS16550_LINE_STATUS);
+ } while ((status & SP_LSR_THOLD) == 0);
+ }
+
+ /* Restore port interrupt mask */
+ set( port, NS16550_INTERRUPT_ENABLE, interrupt_mask);
+}
+
+/*
+ * These routines provide control of the RTS and DTR lines
+ */
+
+/*
+ * ns16550_assert_RTS
+ */
+
+static void ns16550_assert_RTS(rtems_termios_device_context *base)
+{
+ ns16550_context *ctx = (ns16550_context *) base;
+ rtems_interrupt_lock_context lock_context;
+
+ /*
+ * Assert RTS
+ */
+ rtems_termios_device_lock_acquire(base, &lock_context);
+ ctx->modem_control |= SP_MODEM_RTS;
+ (*ctx->set_reg)(ctx->port, NS16550_MODEM_CONTROL, ctx->modem_control);
+ rtems_termios_device_lock_release(base, &lock_context);
+}
+
+/*
+ * ns16550_negate_RTS
+ */
+
+static void ns16550_negate_RTS(rtems_termios_device_context *base)
+{
+ ns16550_context *ctx = (ns16550_context *) base;
+ rtems_interrupt_lock_context lock_context;
+
+ /*
+ * Negate RTS
+ */
+ rtems_termios_device_lock_acquire(base, &lock_context);
+ ctx->modem_control &= ~SP_MODEM_RTS;
+ (*ctx->set_reg)(ctx->port, NS16550_MODEM_CONTROL, ctx->modem_control);
+ rtems_termios_device_lock_release(base, &lock_context);
+}
+
+/*
+ * These flow control routines utilise a connection from the local DTR
+ * line to the remote CTS line
+ */
+
+/*
+ * ns16550_assert_DTR
+ */
+
+static void ns16550_assert_DTR(rtems_termios_device_context *base)
+{
+ ns16550_context *ctx = (ns16550_context *) base;
+ rtems_interrupt_lock_context lock_context;
+
+ /*
+ * Assert DTR
+ */
+ rtems_termios_device_lock_acquire(base, &lock_context);
+ ctx->modem_control |= SP_MODEM_DTR;
+ (*ctx->set_reg)(ctx->port, NS16550_MODEM_CONTROL, ctx->modem_control);
+ rtems_termios_device_lock_release(base, &lock_context);
+}
+
+/*
+ * ns16550_negate_DTR
+ */
+
+static void ns16550_negate_DTR(rtems_termios_device_context *base)
+{
+ ns16550_context *ctx = (ns16550_context *) base;
+ rtems_interrupt_lock_context lock_context;
+
+ /*
+ * Negate DTR
+ */
+ rtems_termios_device_lock_acquire(base, &lock_context);
+ ctx->modem_control &=~SP_MODEM_DTR;
+ (*ctx->set_reg)(ctx->port, NS16550_MODEM_CONTROL,ctx->modem_control);
+ rtems_termios_device_lock_release(base, &lock_context);
+}
+
+/*
+ * ns16550_set_attributes
+ *
+ * This function sets the channel to reflect the requested termios
+ * port settings.
+ */
+
+static bool ns16550_set_attributes(
+ rtems_termios_device_context *base,
+ const struct termios *t
+)
+{
+ ns16550_context *ctx = (ns16550_context *) base;
+ uint32_t pNS16550;
+ uint32_t ulBaudDivisor;
+ uint8_t ucLineControl;
+ uint32_t baud_requested;
+ ns16550_set_reg setReg;
+ rtems_interrupt_lock_context lock_context;
+
+ pNS16550 = ctx->port;
+ setReg = ctx->set_reg;
+
+ /*
+ * Calculate the baud rate divisor
+ */
+
+ baud_requested = rtems_termios_baud_to_number(t->c_cflag);
+ ulBaudDivisor = NS16550_GetBaudDivisor(ctx, baud_requested);
+
+ ucLineControl = 0;
+
+ /*
+ * Parity
+ */
+
+ if (t->c_cflag & PARENB) {
+ ucLineControl |= SP_LINE_PAR;
+ if (!(t->c_cflag & PARODD))
+ ucLineControl |= SP_LINE_ODD;
+ }
+
+ /*
+ * Character Size
+ */
+
+ if (t->c_cflag & CSIZE) {
+ switch (t->c_cflag & CSIZE) {
+ case CS5: ucLineControl |= FIVE_BITS; break;
+ case CS6: ucLineControl |= SIX_BITS; break;
+ case CS7: ucLineControl |= SEVEN_BITS; break;
+ case CS8: ucLineControl |= EIGHT_BITS; break;
+ }
+ } else {
+ ucLineControl |= EIGHT_BITS; /* default to 9600,8,N,1 */
+ }
+
+ /*
+ * Stop Bits
+ */
+
+ if (t->c_cflag & CSTOPB) {
+ ucLineControl |= SP_LINE_STOP; /* 2 stop bits */
+ } else {
+ ; /* 1 stop bit */
+ }
+
+ /*
+ * Now actually set the chip
+ */
+
+ rtems_termios_device_lock_acquire(base, &lock_context);
+
+ /*
+ * Set the baud rate
+ *
+ * NOTE: When the Divisor Latch Access Bit (DLAB) is set to 1,
+ * the transmit buffer and interrupt enable registers
+ * turn into the LSB and MSB divisor latch registers.
+ */
+
+ (*setReg)(pNS16550, NS16550_LINE_CONTROL, SP_LINE_DLAB);
+ (*setReg)(pNS16550, NS16550_TRANSMIT_BUFFER, ulBaudDivisor&0xff);
+ (*setReg)(pNS16550, NS16550_INTERRUPT_ENABLE, (ulBaudDivisor>>8)&0xff);
+
+ /*
+ * Now write the line control
+ */
+ (*setReg)(pNS16550, NS16550_LINE_CONTROL, ucLineControl );
+
+ rtems_termios_device_lock_release(base, &lock_context);
+
+ return true;
+}
+
+/**
+ * @brief Transmits up to @a len characters from @a buf.
+ *
+ * This routine is invoked either from task context with disabled interrupts to
+ * start a new transmission process with exactly one character in case of an
+ * idle output state or from the interrupt handler to refill the transmitter.
+ *
+ * Returns always zero.
+ */
+static void ns16550_write_support_int(
+ rtems_termios_device_context *base,
+ const char *buf,
+ size_t len
+)
+{
+ ns16550_context *ctx = (ns16550_context *) base;
+ uint32_t port = ctx->port;
+ ns16550_set_reg set = ctx->set_reg;
+ int i = 0;
+ int out = len > SP_FIFO_SIZE ? SP_FIFO_SIZE : len;
+
+ for (i = 0; i < out; ++i) {
+ set( port, NS16550_TRANSMIT_BUFFER, buf [i]);
+ }
+
+ ctx->transmit_fifo_chars = out;
+
+ if (out > 0) {
+ ns16550_enable_interrupts(ctx, NS16550_ENABLE_ALL_INTR);
+ } else {
+ ns16550_enable_interrupts(ctx, NS16550_ENABLE_ALL_INTR_EXCEPT_TX);
+ }
+}
+
+/*
+ * ns16550_write_support_polled
+ *
+ * Console Termios output entry point.
+ *
+ */
+
+static void ns16550_write_support_polled(
+ rtems_termios_device_context *base,
+ const char *buf,
+ size_t len
+)
+{
+ size_t nwrite = 0;
+
+ /*
+ * poll each byte in the string out of the port.
+ */
+ while (nwrite < len) {
+ /*
+ * transmit character
+ */
+ ns16550_polled_putchar(base, *buf++);
+ nwrite++;
+ }
+}
+
+/*
+ * Debug gets() support
+ */
+int ns16550_polled_getchar(rtems_termios_device_context *base)
+{
+ ns16550_context *ctx = (ns16550_context *) base;
+ uint32_t pNS16550;
+ unsigned char ucLineStatus;
+ uint8_t cChar;
+ ns16550_get_reg getReg;
+
+ pNS16550 = ctx->port;
+ getReg = ctx->get_reg;
+
+ ucLineStatus = (*getReg)(pNS16550, NS16550_LINE_STATUS);
+ if (ucLineStatus & SP_LSR_RDY) {
+ cChar = (*getReg)(pNS16550, NS16550_RECEIVE_BUFFER);
+ return (int)cChar;
+ }
+ return -1;
+}
+
+/*
+ * Flow control is only supported when using interrupts
+ */
+
+const rtems_termios_device_flow ns16550_flow_rtscts = {
+ .stop_remote_tx = ns16550_negate_RTS,
+ .start_remote_tx = ns16550_assert_RTS
+};
+
+const rtems_termios_device_flow ns16550_flow_dtrcts = {
+ .stop_remote_tx = ns16550_negate_DTR,
+ .start_remote_tx = ns16550_assert_DTR
+};
+
+const rtems_termios_device_handler ns16550_handler_interrupt = {
+ .first_open = ns16550_open,
+ .last_close = ns16550_close,
+ .poll_read = NULL,
+ .write = ns16550_write_support_int,
+ .set_attributes = ns16550_set_attributes,
+ .mode = TERMIOS_IRQ_DRIVEN
+};
+
+const rtems_termios_device_handler ns16550_handler_polled = {
+ .first_open = ns16550_open,
+ .last_close = ns16550_close,
+ .poll_read = ns16550_polled_getchar,
+ .write = ns16550_write_support_polled,
+ .set_attributes = ns16550_set_attributes,
+ .mode = TERMIOS_POLLED
+};
diff --git a/c/src/libchip/serial/ns16550.c b/c/src/libchip/serial/ns16550.c
index 390c729..b0aa38f 100644
--- a/c/src/libchip/serial/ns16550.c
+++ b/c/src/libchip/serial/ns16550.c
@@ -58,6 +58,82 @@
#endif
#endif

+typedef struct {
+ uint8_t ucModemCtrl;
+ int transmitFifoChars;
+} NS16550Context;
+
+/*
+ * Driver functions
+ */
+
+NS16550_STATIC void ns16550_init(int minor);
+
+NS16550_STATIC int ns16550_open(
+ int major,
+ int minor,
+ void * arg
+);
+
+NS16550_STATIC int ns16550_close(
+ int major,
+ int minor,
+ void * arg
+);
+
+NS16550_STATIC void ns16550_write_polled(
+ int minor,
+ char cChar
+);
+
+NS16550_STATIC int ns16550_assert_RTS(
+ int minor
+);
+
+NS16550_STATIC int ns16550_negate_RTS(
+ int minor
+);
+
+NS16550_STATIC int ns16550_assert_DTR(
+ int minor
+);
+
+NS16550_STATIC int ns16550_negate_DTR(
+ int minor
+);
+
+NS16550_STATIC void ns16550_initialize_interrupts(int minor);
+
+NS16550_STATIC void ns16550_cleanup_interrupts(int minor);
+
+NS16550_STATIC ssize_t ns16550_write_support_int(
+ int minor,
+ const char *buf,
+ size_t len
+);
+
+NS16550_STATIC ssize_t ns16550_write_support_polled(
+ int minor,
+ const char *buf,
+ size_t len
+ );
+
+int ns16550_inbyte_nonblocking_polled(
+ int minor
+);
+
+NS16550_STATIC void ns16550_enable_interrupts(
+ console_tbl *c,
+ int mask
+);
+
+NS16550_STATIC int ns16550_set_attributes(
+ int minor,
+ const struct termios *t
+);
+
+NS16550_STATIC void ns16550_isr(void *arg);
+
static rtems_interrupt_lock ns16550_lock =
RTEMS_INTERRUPT_LOCK_INITIALIZER("NS16550");

@@ -142,12 +218,12 @@ void ns16550_init(int minor)
uintptr_t pNS16550;
uint8_t ucDataByte;
uint32_t ulBaudDivisor;
- ns16550_context *pns16550Context;
+ NS16550Context *pns16550Context;
setRegister_f setReg;
getRegister_f getReg;
console_tbl *c = Console_Port_Tbl [minor];

- pns16550Context=(ns16550_context *)malloc(sizeof(ns16550_context));
+ pns16550Context=(NS16550Context *)malloc(sizeof(NS16550Context));

if (pns16550Context == NULL) {
printk( "%s: Error: Not enough memory\n", __func__);
@@ -328,10 +404,10 @@ NS16550_STATIC int ns16550_assert_RTS(int minor)
{
uint32_t pNS16550;
rtems_interrupt_lock_context lock_context;
- ns16550_context *pns16550Context;
+ NS16550Context *pns16550Context;
setRegister_f setReg;

- pns16550Context=(ns16550_context *) Console_Port_Data[minor].pDeviceContext;
+ pns16550Context=(NS16550Context *) Console_Port_Data[minor].pDeviceContext;

pNS16550 = Console_Port_Tbl[minor]->ulCtrlPort1;
setReg = Console_Port_Tbl[minor]->setRegister;
@@ -354,10 +430,10 @@ NS16550_STATIC int ns16550_negate_RTS(int minor)
{
uint32_t pNS16550;
rtems_interrupt_lock_context lock_context;
- ns16550_context *pns16550Context;
+ NS16550Context *pns16550Context;
setRegister_f setReg;

- pns16550Context=(ns16550_context *) Console_Port_Data[minor].pDeviceContext;
+ pns16550Context=(NS16550Context *) Console_Port_Data[minor].pDeviceContext;

pNS16550 = Console_Port_Tbl[minor]->ulCtrlPort1;
setReg = Console_Port_Tbl[minor]->setRegister;
@@ -385,10 +461,10 @@ NS16550_STATIC int ns16550_assert_DTR(int minor)
{
uint32_t pNS16550;
rtems_interrupt_lock_context lock_context;
- ns16550_context *pns16550Context;
+ NS16550Context *pns16550Context;
setRegister_f setReg;

- pns16550Context=(ns16550_context *) Console_Port_Data[minor].pDeviceContext;
+ pns16550Context=(NS16550Context *) Console_Port_Data[minor].pDeviceContext;

pNS16550 = Console_Port_Tbl[minor]->ulCtrlPort1;
setReg = Console_Port_Tbl[minor]->setRegister;
@@ -411,10 +487,10 @@ NS16550_STATIC int ns16550_negate_DTR(int minor)
{
uint32_t pNS16550;
rtems_interrupt_lock_context lock_context;
- ns16550_context *pns16550Context;
+ NS16550Context *pns16550Context;
setRegister_f setReg;

- pns16550Context=(ns16550_context *) Console_Port_Data[minor].pDeviceContext;
+ pns16550Context=(NS16550Context *) Console_Port_Data[minor].pDeviceContext;

pNS16550 = Console_Port_Tbl[minor]->ulCtrlPort1;
setReg = Console_Port_Tbl[minor]->setRegister;
@@ -533,7 +609,7 @@ NS16550_STATIC void ns16550_process( int minor)
{
console_tbl *c = Console_Port_Tbl [minor];
console_data *d = &Console_Port_Data [minor];
- ns16550_context *ctx = d->pDeviceContext;
+ NS16550Context *ctx = d->pDeviceContext;
uint32_t port = c->ulCtrlPort1;
getRegister_f get = c->getRegister;
int i = 0;
@@ -584,7 +660,7 @@ ssize_t ns16550_write_support_int(
{
console_tbl *c = Console_Port_Tbl [minor];
console_data *d = &Console_Port_Data [minor];
- ns16550_context *ctx = d->pDeviceContext;
+ NS16550Context *ctx = d->pDeviceContext;
uint32_t port = c->ulCtrlPort1;
setRegister_f set = c->setRegister;
int i = 0;
diff --git a/c/src/libchip/serial/ns16550.h b/c/src/libchip/serial/ns16550.h
index 2890566..ef1f9f9 100644
--- a/c/src/libchip/serial/ns16550.h
+++ b/c/src/libchip/serial/ns16550.h
@@ -27,6 +27,7 @@
#ifndef _NS16550_H_
#define _NS16550_H_

+#include <rtems/termiostypes.h>
#include <libchip/serial.h>

#ifdef __cplusplus
@@ -53,6 +54,37 @@ extern const console_flow ns16550_flow_DTRCTS;
void ns16550_outch_polled(console_tbl *c, char out);
int ns16550_inch_polled(console_tbl *c);

+/* Alternative NS16550 driver using the Termios device context */
+
+typedef uint8_t (*ns16550_get_reg)(uintptr_t port, uint8_t reg);
+
+typedef void (*ns16550_set_reg)(uintptr_t port, uint8_t reg, uint8_t value);
+
+typedef struct {
+ rtems_termios_device_context base;
+ ns16550_get_reg get_reg;
+ ns16550_set_reg set_reg;
+ uintptr_t port;
+ rtems_vector_number irq;
+ uint32_t clock;
+ uint32_t initial_baud;
+ bool has_fractional_divider_register;
+ uint8_t modem_control;
+ size_t transmit_fifo_chars;
+} ns16550_context;
+
+extern const rtems_termios_device_handler ns16550_handler_interrupt;
+extern const rtems_termios_device_handler ns16550_handler_polled;
+
+extern const rtems_termios_device_flow ns16550_flow_rtscts;
+extern const rtems_termios_device_flow ns16550_flow_dtrcts;
+
+void ns16550_polled_putchar(rtems_termios_device_context *base, char out);
+
+int ns16550_polled_getchar(rtems_termios_device_context *base);
+
+bool ns16550_probe(rtems_termios_device_context *base);
+
#ifdef __cplusplus
}
#endif
diff --git a/c/src/libchip/serial/ns16550_p.h b/c/src/libchip/serial/ns16550_p.h
index 4e6d784..0fe817a 100644
--- a/c/src/libchip/serial/ns16550_p.h
+++ b/c/src/libchip/serial/ns16550_p.h
@@ -131,82 +131,6 @@ extern "C" {
#define SP_LSR_TX 0x40
#define SP_LSR_EFIFO 0x80

-typedef struct {
- uint8_t ucModemCtrl;
- int transmitFifoChars;
-} ns16550_context;
-
-/*
- * Driver functions
- */
-
-void ns16550_init(int minor);
-
-int ns16550_open(
- int major,
- int minor,
- void * arg
-);
-
-int ns16550_close(
- int major,
- int minor,
- void * arg
-);
-
-void ns16550_write_polled(
- int minor,
- char cChar
-);
-
-NS16550_STATIC int ns16550_assert_RTS(
- int minor
-);
-
-NS16550_STATIC int ns16550_negate_RTS(
- int minor
-);
-
-NS16550_STATIC int ns16550_assert_DTR(
- int minor
-);
-
-NS16550_STATIC int ns16550_negate_DTR(
- int minor
-);
-
-NS16550_STATIC void ns16550_initialize_interrupts(int minor);
-
-NS16550_STATIC void ns16550_cleanup_interrupts(int minor);
-
-ssize_t ns16550_write_support_int(
- int minor,
- const char *buf,
- size_t len
-);
-
-ssize_t ns16550_write_support_polled(
- int minor,
- const char *buf,
- size_t len
- );
-
-int ns16550_inbyte_nonblocking_polled(
- int minor
-);
-
-NS16550_STATIC void ns16550_enable_interrupts(
- console_tbl *c,
- int mask
-);
-
-int ns16550_set_attributes(
- int minor,
- const struct termios *t
-);
-
-void ns16550_isr(void *arg);
-
#ifdef __cplusplus
}
#endif
--
1.8.4.5
Loading...