diff options
author | dyson <dyson@FreeBSD.org> | 1997-08-09 01:43:15 +0000 |
---|---|---|
committer | dyson <dyson@FreeBSD.org> | 1997-08-09 01:43:15 +0000 |
commit | 305573cb2990c5d329d149cef5a3b5533b1e8fd9 (patch) | |
tree | df06304b637358dbe8a006fdb7a6ea5955fee179 /usr.bin/doscmd/callback.c | |
parent | dede28832bba6a9de7a428ff58df92439bddbc9c (diff) | |
download | FreeBSD-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.c | 120 |
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)); +} |