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