aboutsummaryrefslogtreecommitdiff
path: root/device/cirbuf.c
diff options
context:
space:
mode:
authorPasha <pasha@member.fsf.org>2024-02-20 18:49:50 +0000
committerPasha <pasha@member.fsf.org>2024-02-20 18:49:50 +0000
commit5e0b8d508ed51004bd836384293be00950ee62c9 (patch)
treee3f16b1aa8b7177032ce3ec429fbad2b1d92a876 /device/cirbuf.c
downloadgnumach-riscv-5e0b8d508ed51004bd836384293be00950ee62c9.tar.gz
gnumach-riscv-5e0b8d508ed51004bd836384293be00950ee62c9.tar.bz2
init gnumach copy
Diffstat (limited to 'device/cirbuf.c')
-rw-r--r--device/cirbuf.c277
1 files changed, 277 insertions, 0 deletions
diff --git a/device/cirbuf.c b/device/cirbuf.c
new file mode 100644
index 0000000..ed09f3d
--- /dev/null
+++ b/device/cirbuf.c
@@ -0,0 +1,277 @@
+/*
+ * Mach Operating System
+ * Copyright (c) 1992,1991,1990 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+/*
+ * Author: David B. Golub, Carnegie Mellon University
+ * Date: 7/90
+ *
+ * Circular buffers for TTY
+ */
+
+#include <string.h>
+#include <device/cirbuf.h>
+#include <kern/debug.h>
+#include <kern/kalloc.h>
+
+
+
+/* read at c_cf, write at c_cl */
+/* if c_cf == c_cl, buffer is empty */
+/* if c_cl == c_cf - 1, buffer is full */
+
+#if DEBUG
+#include <mach/boolean.h>
+
+boolean_t cb_check_enable = FALSE;
+#define CB_CHECK(cb) if (cb_check_enable) cb_check(cb)
+
+void
+cb_check(struct cirbuf *cb)
+{
+ if (!(cb->c_cf >= cb->c_start && cb->c_cf < cb->c_end))
+ panic("cf %p out of range [%p..%p)",
+ cb->c_cf, cb->c_start, cb->c_end);
+ if (!(cb->c_cl >= cb->c_start && cb->c_cl < cb->c_end))
+ panic("cl %p out of range [%p..%p)",
+ cb->c_cl, cb->c_start, cb->c_end);
+ if (cb->c_cf <= cb->c_cl) {
+ if (!(cb->c_cc == cb->c_cl - cb->c_cf))
+ panic("cc %x should be %x",
+ cb->c_cc,
+ cb->c_cl - cb->c_cf);
+ }
+ else {
+ if (!(cb->c_cc == cb->c_end - cb->c_cf
+ + cb->c_cl - cb->c_start))
+ panic("cc %x should be %x",
+ cb->c_cc,
+ cb->c_end - cb->c_cf +
+ cb->c_cl - cb->c_start);
+ }
+}
+#else /* DEBUG */
+#define CB_CHECK(cb)
+#endif /* DEBUG */
+
+/*
+ * Put one character in circular buffer.
+ */
+int putc(
+ int c,
+ struct cirbuf *cb)
+{
+ char *ow, *nw;
+
+ ow = cb->c_cl;
+ nw = ow+1;
+ if (nw == cb->c_end)
+ nw = cb->c_start;
+ if (nw == cb->c_cf)
+ return 1; /* not entered */
+ *ow = c;
+ cb->c_cl = nw;
+
+ cb->c_cc++;
+
+ CB_CHECK(cb);
+
+ return 0;
+}
+
+/*
+ * Get one character from circular buffer.
+ */
+int getc(struct cirbuf *cb)
+{
+ unsigned char *nr;
+ int c;
+
+ nr = (unsigned char *)cb->c_cf;
+ if (nr == (unsigned char *)cb->c_cl) {
+ CB_CHECK(cb);
+ return -1; /* empty */
+ }
+ c = *nr;
+ nr++;
+ if (nr == (unsigned char *)cb->c_end)
+ nr = (unsigned char *)cb->c_start;
+ cb->c_cf = (char *)nr;
+
+ cb->c_cc--;
+
+ CB_CHECK(cb);
+
+ return c;
+}
+
+/*
+ * Get lots of characters.
+ * Return number moved.
+ */
+int
+q_to_b( struct cirbuf *cb,
+ char *cp,
+ int count)
+{
+ char *ocp = cp;
+ int i;
+
+ while (count != 0) {
+ if (cb->c_cl == cb->c_cf)
+ break; /* empty */
+ if (cb->c_cl < cb->c_cf)
+ i = cb->c_end - cb->c_cf;
+ else
+ i = cb->c_cl - cb->c_cf;
+ if (i > count)
+ i = count;
+ memcpy(cp, cb->c_cf, i);
+ cp += i;
+ count -= i;
+ cb->c_cf += i;
+ cb->c_cc -= i;
+ if (cb->c_cf == cb->c_end)
+ cb->c_cf = cb->c_start;
+
+ CB_CHECK(cb);
+ }
+ CB_CHECK(cb);
+
+ return cp - ocp;
+}
+
+/*
+ * Add character array to buffer and return number of characters
+ * NOT entered.
+ */
+int
+b_to_q( char *cp,
+ int count,
+ struct cirbuf *cb)
+{
+ int i;
+ char *lim;
+
+ while (count != 0) {
+ lim = cb->c_cf - 1;
+ if (lim < cb->c_start)
+ lim = cb->c_end - 1;
+
+ if (cb->c_cl == lim)
+ break;
+ if (cb->c_cl < lim)
+ i = lim - cb->c_cl;
+ else
+ i = cb->c_end - cb->c_cl;
+
+ if (i > count)
+ i = count;
+ memcpy(cb->c_cl, cp, i);
+ cp += i;
+ count -= i;
+ cb->c_cc += i;
+ cb->c_cl += i;
+ if (cb->c_cl == cb->c_end)
+ cb->c_cl = cb->c_start;
+
+ CB_CHECK(cb);
+ }
+ CB_CHECK(cb);
+ return count;
+}
+
+/*
+ * Flush characters from circular buffer.
+ */
+void
+ndflush(struct cirbuf *cb,
+ int count)
+{
+ int i;
+
+ while (count != 0) {
+ if (cb->c_cl == cb->c_cf)
+ break; /* empty */
+ if (cb->c_cl < cb->c_cf)
+ i = cb->c_end - cb->c_cf;
+ else
+ i = cb->c_cl - cb->c_cf;
+ if (i > count)
+ i = count;
+ count -= i;
+ cb->c_cf += i;
+ cb->c_cc -= i;
+ if (cb->c_cf == cb->c_end)
+ cb->c_cf = cb->c_start;
+ CB_CHECK(cb);
+ }
+
+ CB_CHECK(cb);
+}
+
+/*
+ * Empty a circular buffer.
+ */
+void cb_clear(struct cirbuf *cb)
+{
+ cb->c_cf = cb->c_start;
+ cb->c_cl = cb->c_start;
+ cb->c_cc = 0;
+}
+
+/*
+ * Allocate character space for a circular buffer.
+ */
+void
+cb_alloc(
+ struct cirbuf *cb,
+ vm_size_t buf_size)
+{
+ char *buf;
+
+ buf = (char *)kalloc(buf_size);
+
+ cb->c_start = buf;
+ cb->c_end = buf + buf_size;
+ cb->c_cf = buf;
+ cb->c_cl = buf;
+ cb->c_cc = 0;
+ cb->c_hog = buf_size - 1;
+
+ CB_CHECK(cb);
+}
+
+/*
+ * Free character space for a circular buffer.
+ */
+void
+cb_free(struct cirbuf *cb)
+{
+ vm_size_t size;
+
+ size = cb->c_end - cb->c_start;
+ kfree((vm_offset_t)cb->c_start, size);
+}
+