Merge branch 'vendor/BINUTILS221'
[dragonfly.git] / usr.bin / doscmd / callback.c
1 /*
2  * No copyright?!
3  *
4  * $FreeBSD: src/usr.bin/doscmd/callback.c,v 1.2.2.2 2002/04/25 11:04:50 tg Exp $
5  * $DragonFly: src/usr.bin/doscmd/callback.c,v 1.2 2003/06/17 04:29:25 dillon Exp $
6  */
7
8 #include <sys/queue.h>
9 #include "doscmd.h"
10
11 /*
12 ** Callbacks are used for chaining interrupt handlers 
13 ** off interrupt vectors
14 */
15
16 struct callback {
17     LIST_ENTRY(callback) chain;
18     u_long vec;
19     callback_t func;
20     const char *name;
21 };
22
23 LIST_HEAD(cbhead , callback) cbhead[127];
24
25 #define CBHASH(x)       (((x) * 17) % 127)
26
27 /*
28 ** Register (func) as a handler for (vec)
29 */
30 void
31 register_callback(u_long vec, callback_t func, const char *name)
32 {
33     struct cbhead *head;
34     struct callback *elm;
35
36     elm = malloc(sizeof(struct callback));
37     elm->vec = vec;
38     elm->func = func;
39     elm->name = name;
40     
41     head = &cbhead[CBHASH(vec)];
42     LIST_INSERT_HEAD(head, elm, chain);
43 }
44
45 /*
46 ** Find a handler for (vec)
47 */
48 callback_t
49 find_callback(u_long vec)
50 {
51     struct cbhead *head;
52     struct callback *elm;
53
54     head = &cbhead[CBHASH(vec)];
55     LIST_FOREACH(elm, head, chain)
56         if (elm->vec == vec)
57             break;
58     if (elm) {
59         debug(D_TRAPS2, "callback %s\n", elm->name);
60         return (elm->func);
61     } else
62         return ((callback_t)0);
63 }
64
65 u_long trampoline_rover = 0xF1000000;
66
67 /*
68  * Interrupts are disabled on an INTn call, so we must restore interrupts
69  * before via STI returning.  IRET is not used here because 1) some DOS
70  * calls want to return status via the FLAGS register, and 2) external
71  * routines which hook INTn calls do not always put a FLAGS image on the
72  * stack which re-enables interrupts.
73  */
74 u_char softint_trampoline[] = {
75     0xf4,       /* HLT */
76     0xfb,       /* STI */
77     0xca,       /* RETF 2 */
78     2,
79     0,
80 };
81 u_char hardint_trampoline[] = {
82     0xf4,       /* HLT */
83     0xcf,       /* IRET */
84 };
85 u_char null_trampoline[] = {
86     0xcf,       /* IRET */
87 };
88
89 u_long
90 insert_generic_trampoline(size_t len, u_char *p)
91 {
92     u_char *q;
93     u_long where;
94
95     where = trampoline_rover;
96     q = (u_char *)VECPTR(where);
97     memcpy(q, p, len);
98     trampoline_rover += len;
99     return (where);
100 }
101
102 u_long
103 insert_softint_trampoline(void)
104 {
105     return (insert_generic_trampoline(
106         sizeof(softint_trampoline), softint_trampoline));
107 }
108
109 u_long
110 insert_hardint_trampoline(void)
111 {
112     return (insert_generic_trampoline(
113         sizeof(hardint_trampoline), hardint_trampoline));
114 }
115
116 u_long
117 insert_null_trampoline(void)
118 {
119     return (insert_generic_trampoline(
120         sizeof(null_trampoline), null_trampoline));
121 }