From a52008cb44a01969383ee92966a3c03d55911b46 Mon Sep 17 00:00:00 2001 From: Adrien Destugues Date: Sun, 26 Apr 2020 11:43:54 +0200 Subject: [PATCH] tty: implement TCFLSH to flush buffers This is probably incomplete. Is locking needed? Should we notify the next writer (if any) that the port is writable when flushing the output? Change-Id: I2566e2d036a61af4819894a44f57603179aa27df Reviewed-on: https://review.haiku-os.org/c/haiku/+/2516 Reviewed-by: Adrien Destugues --- headers/os/drivers/tty/tty_module.h | 1 + .../drivers/ports/pc_serial/SerialDevice.cpp | 13 +++++++++++ .../drivers/ports/usb_serial/SerialDevice.cpp | 1 + src/add-ons/kernel/generic/tty/tty.cpp | 22 +++++++++++++++++++ 4 files changed, 37 insertions(+) diff --git a/headers/os/drivers/tty/tty_module.h b/headers/os/drivers/tty/tty_module.h index 3229e87059..3993242129 100644 --- a/headers/os/drivers/tty/tty_module.h +++ b/headers/os/drivers/tty/tty_module.h @@ -39,6 +39,7 @@ typedef bool (*tty_service_func)(struct tty *tty, uint32 op, void *buffer, #define TTYSETDTR 6 /* bool dataTerminalReady */ #define TTYSETRTS 7 /* bool requestToSend */ #define TTYGETSIGNALS 8 /* call tty_hardware_signal for all bits */ +#define TTYFLUSH 9 /* clear input and/or output buffers */ typedef struct tty_module_info tty_module_info; diff --git a/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.cpp b/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.cpp index 7e482db3e5..b473831329 100644 --- a/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.cpp +++ b/src/add-ons/kernel/drivers/ports/pc_serial/SerialDevice.cpp @@ -359,6 +359,19 @@ SerialDevice::Service(struct tty *tty, uint32 op, void *buffer, size_t length) return true; } + case TTYFLUSH: + { + int directions = *(int*)buffer; + uint8 mask = 0; + if (directions & TCIFLUSH) + mask |= FCR_RX_RST; + if (directions & TCOFLUSH) + mask |= FCR_TX_RST; + // These bits clear themselves when flushing is complete + OrReg8(FCR, mask); + + return true; + } default: return false; } diff --git a/src/add-ons/kernel/drivers/ports/usb_serial/SerialDevice.cpp b/src/add-ons/kernel/drivers/ports/usb_serial/SerialDevice.cpp index b9c5521192..93f517fc65 100644 --- a/src/add-ons/kernel/drivers/ports/usb_serial/SerialDevice.cpp +++ b/src/add-ons/kernel/drivers/ports/usb_serial/SerialDevice.cpp @@ -274,6 +274,7 @@ SerialDevice::Service(struct tty *tty, uint32 op, void *buffer, size_t length) case TTYOSTART: case TTYOSYNC: case TTYSETBREAK: + case TTYFLUSH: TRACE("TTY other\n"); return true; } diff --git a/src/add-ons/kernel/generic/tty/tty.cpp b/src/add-ons/kernel/generic/tty/tty.cpp index 8d09fa95c6..3a8053affb 100644 --- a/src/add-ons/kernel/generic/tty/tty.cpp +++ b/src/add-ons/kernel/generic/tty/tty.cpp @@ -1810,6 +1810,28 @@ tty_control(tty_cookie* cookie, uint32 op, void* buffer, size_t length) return B_ERROR; } + + case TCFLSH: + { + int value; + if (user_memcpy(&value, buffer, sizeof(value)) != B_OK) + return B_BAD_ADDRESS; + if (value & TCOFLUSH) { + struct tty* otherTTY = cookie->other_tty; + if (otherTTY->open_count <= 0) + return B_ERROR; + + clear_line_buffer(otherTTY->input_buffer); + } + + if (value & TCIFLUSH) + clear_line_buffer(tty->input_buffer); + + if (tty->service_func(tty, TTYFLUSH, &value, sizeof(value))) + return B_OK; + + return B_ERROR; + } } TRACE(("tty: unsupported opcode %lu\n", op));