summaryrefslogtreecommitdiff
path: root/sys/dev/wscons/wsemulvar.h
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2009-09-05 14:49:21 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2009-09-05 14:49:21 +0000
commitec17529a5bd62e044b53345c38f067d1451d619b (patch)
tree4db8b16a998a02869773fbb021ddbd2d11ca0d63 /sys/dev/wscons/wsemulvar.h
parentc818bfbdec899fc627d95f7d7149b9425f7f9188 (diff)
Check the return value of all emulops in the emulation code, and abort
tty output as soon as we hit a failure. Since the `output' of a character may cause several emulops to be called (e.g. if it causes scrollup or if this is the end of an escape sequence), all emulation code maintain a so-called `abort state', to be able to properly recover when the character is tentatively output later, and not reissue the emulops which did not fail the first time. With help from mglocker@
Diffstat (limited to 'sys/dev/wscons/wsemulvar.h')
-rw-r--r--sys/dev/wscons/wsemulvar.h114
1 files changed, 113 insertions, 1 deletions
diff --git a/sys/dev/wscons/wsemulvar.h b/sys/dev/wscons/wsemulvar.h
index a4370ce7c69..23358af2ae4 100644
--- a/sys/dev/wscons/wsemulvar.h
+++ b/sys/dev/wscons/wsemulvar.h
@@ -1,7 +1,22 @@
-/* $OpenBSD: wsemulvar.h,v 1.11 2009/09/05 14:30:24 miod Exp $ */
+/* $OpenBSD: wsemulvar.h,v 1.12 2009/09/05 14:49:20 miod Exp $ */
/* $NetBSD: wsemulvar.h,v 1.6 1999/01/17 15:46:15 drochner Exp $ */
/*
+ * Copyright (c) 2009 Miodrag Vallat.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
* Copyright (c) 1996, 1997 Christopher G. Demetriou. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,6 +46,8 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+#ifdef _KERNEL
+
struct device;
struct wsdisplay_emulops;
@@ -65,3 +82,98 @@ const struct wsemul_ops *wsemul_pick(const char *);
*/
void wsdisplay_emulbell(void *v);
void wsdisplay_emulinput(void *v, const u_char *, u_int);
+
+/*
+ * emulops failure abort/recovery state
+ *
+ * The tty layer needs a character output to be atomic. Since this may
+ * expand to multiple emulops operations, which may fail, it is necessary
+ * for each emulation code to keep state of its current processing, so
+ * that if an operation fails, the whole character from the tty layer is
+ * reported as not having been output, while it has in fact been partly
+ * processed.
+ *
+ * When the tty layer will try to retransmit the character, this state
+ * information is used to not retrig the emulops which have been issued
+ * succesfully already.
+ *
+ * In order to make things more confusing, there is a particular failure
+ * case, when all characters have been processed successfully, but
+ * displaying the cursor image fails.
+ *
+ * Since there might not be tty output in a while, we need to report
+ * failure, so we pretend not having been able to issue the last character.
+ * When the tty layer tries again to display this character (really to get
+ * the cursor image back), it will directly be skipped. This is done with
+ * a special state value.
+ */
+
+struct wsemul_abortstate {
+ enum {
+ ABORT_OK,
+ ABORT_FAILED_CURSOR,
+ ABORT_FAILED_JUMP_SCROLL,
+ ABORT_FAILED_OTHER
+ } state;
+ int skip; /* emulops to skip before reaching resume point */
+ int done; /* emulops completed */
+ int lines; /* jump scroll lines */
+};
+
+/* start character processing, assuming cursor or jump scroll failure condition
+ has been taken care of */
+static __inline__ void
+wsemul_resume_abort(struct wsemul_abortstate *was)
+{
+ was->state = ABORT_OK;
+ was->done = 0;
+}
+
+/* register processing failure points */
+static __inline__ void
+wsemul_abort_cursor(struct wsemul_abortstate *was)
+{
+ was->state = ABORT_FAILED_CURSOR;
+}
+
+static __inline__ void
+wsemul_abort_jump_scroll(struct wsemul_abortstate *was, int lines)
+{
+ was->state = ABORT_FAILED_JUMP_SCROLL;
+ was->skip = was->done;
+ was->lines = lines;
+}
+
+static __inline__ void
+wsemul_abort_other(struct wsemul_abortstate *was)
+{
+ was->state = ABORT_FAILED_OTHER;
+ was->skip = was->done;
+}
+
+/* initialize abortstate structure */
+static __inline__ void
+wsemul_reset_abortstate(struct wsemul_abortstate *was)
+{
+ was->state = ABORT_OK;
+ was->skip = 0;
+ /* was->done = 0; */
+}
+
+/*
+ * Wrapper macro to handle failing emulops calls consistently.
+ */
+
+#define WSEMULOP(rc, edp, was, rutin, args) \
+do { \
+ if ((was)->skip != 0) { \
+ (was)->skip--; \
+ (rc) = 0; \
+ } else { \
+ (rc) = (*(edp)->emulops->rutin) args ; \
+ } \
+ if ((rc) == 0) \
+ (was)->done++; \
+} while (0)
+
+#endif /* _KERNEL */