summaryrefslogtreecommitdiffstats
path: root/usr.bin/doscmd/callback.c
diff options
context:
space:
mode:
authordyson <dyson@FreeBSD.org>1997-08-09 01:43:15 +0000
committerdyson <dyson@FreeBSD.org>1997-08-09 01:43:15 +0000
commit305573cb2990c5d329d149cef5a3b5533b1e8fd9 (patch)
treedf06304b637358dbe8a006fdb7a6ea5955fee179 /usr.bin/doscmd/callback.c
parentdede28832bba6a9de7a428ff58df92439bddbc9c (diff)
downloadFreeBSD-src-305573cb2990c5d329d149cef5a3b5533b1e8fd9.zip
FreeBSD-src-305573cb2990c5d329d149cef5a3b5533b1e8fd9.tar.gz
Add our doscmd to the tree. This is a result of work from BSDI, and
a group of dos emulator developers. Submitted by: Jonathan Lemon <jlemon@americantv.com> Obtained from: BSDI
Diffstat (limited to 'usr.bin/doscmd/callback.c')
-rw-r--r--usr.bin/doscmd/callback.c120
1 files changed, 120 insertions, 0 deletions
diff --git a/usr.bin/doscmd/callback.c b/usr.bin/doscmd/callback.c
new file mode 100644
index 0000000..4b333ec
--- /dev/null
+++ b/usr.bin/doscmd/callback.c
@@ -0,0 +1,120 @@
+/* No copyright?!
+**
+** $Id: callback.c,v 1.3 1996/09/24 00:02:25 miff Exp $
+*/
+
+
+#include <sys/queue.h>
+#include "doscmd.h"
+
+/*
+** Callbacks are used for chaining interrupt handlers
+** off interrupt vectors
+*/
+
+struct callback {
+ LIST_ENTRY(callback) chain;
+ u_long vec;
+ callback_t func;
+ char *name;
+};
+
+LIST_HEAD(cbhead , callback) cbhead[127];
+
+#define CBHASH(x) (((x) * 17) % 127)
+
+/*
+** Register (func) as a handler for (vec)
+*/
+void
+register_callback(u_long vec, callback_t func, char *name)
+{
+ struct cbhead *head;
+ struct callback *elm;
+
+ elm = malloc(sizeof(struct callback));
+ elm->vec = vec;
+ elm->func = func;
+ elm->name = name;
+
+ head = &cbhead[CBHASH(vec)];
+ LIST_INSERT_HEAD(head, elm, chain);
+}
+
+/*
+** Find a handler for (vec)
+*/
+callback_t
+find_callback(u_long vec)
+{
+ struct cbhead *head;
+ struct callback *elm;
+
+ head = &cbhead[CBHASH(vec)];
+ for (elm = head->lh_first; elm; elm = elm->chain.le_next)
+ if (elm->vec == vec)
+ break;
+ if (elm) {
+ debug(D_TRAPS2, "callback %s\n", elm->name);
+ return (elm->func);
+ } else
+ return ((callback_t)0);
+}
+
+u_long trampoline_rover = 0xF1000000;
+
+/*
+ * Interrupts are disabled on an INTn call, so we must restore interrupts
+ * before via STI returning. IRET is not used here because 1) some DOS
+ * calls want to return status via the FLAGS register, and 2) external
+ * routines which hook INTn calls do not always put a FLAGS image on the
+ * stack which re-enables interrupts.
+ */
+u_char softint_trampoline[] = {
+ 0xf4, /* HLT */
+ 0xfb, /* STI */
+ 0xca, /* RETF 2 */
+ 2,
+ 0,
+};
+u_char hardint_trampoline[] = {
+ 0xf4, /* HLT */
+ 0xcf, /* IRET */
+};
+u_char null_trampoline[] = {
+ 0xcf, /* IRET */
+};
+
+u_long
+insert_generic_trampoline(size_t len, u_char *p)
+{
+ u_char *q;
+ u_long where;
+
+ where = trampoline_rover;
+ q = (u_char *)VECPTR(where);
+ memcpy(q, p, len);
+ trampoline_rover += len;
+ return (where);
+}
+
+u_long
+insert_softint_trampoline(void)
+{
+ return (insert_generic_trampoline(
+ sizeof(softint_trampoline), softint_trampoline));
+}
+
+u_long
+insert_hardint_trampoline(void)
+{
+ return (insert_generic_trampoline(
+ sizeof(hardint_trampoline), hardint_trampoline));
+}
+
+u_long
+insert_null_trampoline(void)
+{
+ return (insert_generic_trampoline(
+ sizeof(null_trampoline), null_trampoline));
+}
OpenPOWER on IntegriCloud