diff options
-rw-r--r-- | core/console.c | 25 | ||||
-rw-r--r-- | core/platform.c | 4 | ||||
-rw-r--r-- | doc/opal-api/opal-console-read-write-1-2.txt | 16 | ||||
-rw-r--r-- | hw/lpc-uart.c | 30 | ||||
-rw-r--r-- | include/console.h | 4 | ||||
-rw-r--r-- | include/opal-api.h | 3 |
6 files changed, 59 insertions, 23 deletions
diff --git a/core/console.c b/core/console.c index 1cee5da..e851fcf 100644 --- a/core/console.c +++ b/core/console.c @@ -290,10 +290,29 @@ ssize_t read(int fd __unused, void *buf, size_t req_count) return count; } -void flush_console_driver(void) +static int64_t opal_console_flush(int64_t term_number) { - if (con_driver && con_driver->flush != NULL) - con_driver->flush(); + if (term_number != 0) + return OPAL_PARAMETER; + + if (con_driver == NULL || con_driver->flush == NULL) + return OPAL_UNSUPPORTED; + + return con_driver->flush(); +} +opal_call(OPAL_CONSOLE_FLUSH, opal_console_flush, 1); + +/* Helper function to perform a full synchronous flush */ +void console_complete_flush(void) +{ + int64_t ret = opal_console_flush(0); + + if (ret == OPAL_UNSUPPORTED || ret == OPAL_PARAMETER) + return; + + while (ret != OPAL_SUCCESS) { + ret = opal_console_flush(0); + } } void set_console(struct con_ops *driver) diff --git a/core/platform.c b/core/platform.c index 865d5b2..0dfbb88 100644 --- a/core/platform.c +++ b/core/platform.c @@ -37,7 +37,7 @@ static int64_t opal_cec_power_down(uint64_t request) { printf("OPAL: Shutdown request type 0x%llx...\n", request); - flush_console_driver(); + console_complete_flush(); if (platform.cec_power_down) return platform.cec_power_down(request); @@ -50,7 +50,7 @@ static int64_t opal_cec_reboot(void) { printf("OPAL: Reboot request...\n"); - flush_console_driver(); + console_complete_flush(); #ifdef ENABLE_FAST_RESET /* Try a fast reset first */ diff --git a/doc/opal-api/opal-console-read-write-1-2.txt b/doc/opal-api/opal-console-read-write-1-2.txt index b8fbc12..26f9a16 100644 --- a/doc/opal-api/opal-console-read-write-1-2.txt +++ b/doc/opal-api/opal-console-read-write-1-2.txt @@ -1,11 +1,12 @@ OPAL Console calls ------------------ -There are three OPAL calls relating to the OPAL console: +There are four OPAL calls relating to the OPAL console: #define OPAL_CONSOLE_WRITE 1 #define OPAL_CONSOLE_READ 2 #define OPAL_CONSOLE_WRITE_BUFFER_SPACE 25 +#define OPAL_CONSOLE_FLUSH 117 The OPAL console calls can support multiple consoles. Each console MUST be represented in the device tree. @@ -64,3 +65,16 @@ Returns: OPAL_CLOSED Use OPAL_POLL_EVENTS for how to determine + +OPAL_CONSOLE_FLUSH +------------------ + +Parameters: + int64_t term_number + +Returns: + OPAL_SUCCESS + OPAL_UNSUPPORTED - the console does not implement a flush call + OPAL_PARAMETER - invalid term_number + OPAL_PARTIAL - more to flush, call again + OPAL_BUSY - nothing was flushed this call diff --git a/hw/lpc-uart.c b/hw/lpc-uart.c index e856563..2a95da5 100644 --- a/hw/lpc-uart.c +++ b/hw/lpc-uart.c @@ -156,11 +156,11 @@ static size_t uart_con_write(const char *buf, size_t len) return written; } -static void uart_con_flush_all(void); +static int64_t uart_con_flush(void); static struct con_ops uart_con_driver = { .write = uart_con_write, - .flush = uart_con_flush_all + .flush = uart_con_flush }; /* @@ -193,9 +193,11 @@ static uint8_t *out_buf; static uint32_t out_buf_prod; static uint32_t out_buf_cons; -static void uart_flush_out(void) +/* Asynchronous flush */ +static int64_t uart_con_flush(void) { bool tx_was_full = tx_full; + uint32_t out_buf_cons_initial = out_buf_cons; while(out_buf_prod != out_buf_cons) { if (tx_room == 0) { @@ -220,6 +222,15 @@ static void uart_flush_out(void) } if (tx_full != tx_was_full) uart_update_ier(); + if (out_buf_prod != out_buf_cons) { + /* Return busy if nothing was flushed this call */ + if (out_buf_cons == out_buf_cons_initial) + return OPAL_BUSY; + /* Return partial if there's more to flush */ + return OPAL_PARTIAL; + } + + return OPAL_SUCCESS; } static uint32_t uart_tx_buf_space(void) @@ -246,7 +257,7 @@ static int64_t uart_opal_write(int64_t term_number, int64_t *length, } /* Flush out buffer again */ - uart_flush_out(); + uart_con_flush(); unlock(&uart_lock); @@ -357,7 +368,7 @@ static void __uart_do_poll(u8 trace_ctx) lock(&uart_lock); uart_read_to_buffer(); - uart_flush_out(); + uart_con_flush(); uart_trace(trace_ctx, 0, tx_full, in_count); unlock(&uart_lock); @@ -379,15 +390,6 @@ static void uart_irq(uint32_t chip_id __unused, uint32_t irq_mask __unused) } /* - * Flush the entire buffer all at once - */ -static void uart_con_flush_all(void) -{ - while(out_buf_prod != out_buf_cons) - uart_flush_out(); -} - -/* * Common setup/inits */ diff --git a/include/console.h b/include/console.h index 45f914b..b6fc8bf 100644 --- a/include/console.h +++ b/include/console.h @@ -51,7 +51,7 @@ struct con_ops { size_t (*write)(const char *buf, size_t len); size_t (*read)(char *buf, size_t len); bool (*poll_read)(void); - void (*flush)(void); + int64_t (*flush)(void); }; extern struct lock con_lock; @@ -62,7 +62,7 @@ extern bool flush_console(void); extern bool __flush_console(bool flush_to_drivers); extern void set_console(struct con_ops *driver); -extern void flush_console_driver(void); +extern void console_complete_flush(void); extern int mambo_read(void); extern void mambo_write(const char *buf, size_t count); diff --git a/include/opal-api.h b/include/opal-api.h index 7a11fe8..369aa93 100644 --- a/include/opal-api.h +++ b/include/opal-api.h @@ -162,7 +162,8 @@ #define OPAL_LEDS_GET_INDICATOR 114 #define OPAL_LEDS_SET_INDICATOR 115 #define OPAL_CEC_REBOOT2 116 -#define OPAL_LAST 116 +#define OPAL_CONSOLE_FLUSH 117 +#define OPAL_LAST 117 /* Device tree flags */ |