doscmd(1): Raise WARNS to 6 and silence all warnings.
[dragonfly.git] / usr.bin / doscmd / int.c
blob32e89dc4d9fd127d3d8fd783013c97a6294bd644
1 /*
2 ** No copyright?!
3 */
4 /*
5 * Notes:
6 * 1) Second PIC is not implemented.
7 * 2) Interrupt priority management is not implemented.
8 * 3) What should be read from port 0x20?
10 * "within interrupt processing" means the following is true:
11 * 1) Hardware interrupt <irql> is delivered by hardint().
12 * 2) Next interrupt <irql> is not possible yet by either:
13 * a) V_IF;
14 * b) Interrupt mask;
15 * c) Current irql.
17 * Related functions:
18 * int isinhardint(int irql)
19 * void set_eoir(int irql, void (*eoir)(void *), void *arg);
21 * $FreeBSD: src/usr.bin/doscmd/int.c,v 1.3.2.2 2002/04/25 11:04:51 tg Exp $
22 * $DragonFly: src/usr.bin/doscmd/int.c,v 1.2 2003/06/17 04:29:26 dillon Exp $
25 #include "doscmd.h"
27 struct IRQ {
28 int pending;
29 int busy;
30 int within;
31 void (*eoir)(void *arg);
32 void *arg;
35 static unsigned char IM;
36 static int Irql;
37 static struct IRQ Irqs[8];
39 #define int_allowed(n) ((IM & 1 << (n)) == 0 && Irql > (n))
41 void
42 set_eoir(int irql, void (*eoir)(void *), void *arg)
44 Irqs [irql].eoir = eoir;
45 Irqs [irql].arg = arg;
48 int
49 isinhardint(int irql)
51 return Irqs[irql].within;
54 static void
55 set_vip(void)
57 regcontext_t *REGS = saved_regcontext;
58 int irql;
60 if (R_EFLAGS & PSL_VIF) {
61 R_EFLAGS &= ~PSL_VIP;
62 return;
65 for (irql = 0; irql < 8; irql++)
66 if (int_allowed(irql) && (Irqs[irql].within || Irqs[irql].pending)) {
67 R_EFLAGS |= PSL_VIP;
68 return;
71 R_EFLAGS &= ~PSL_VIP;
74 void
75 resume_interrupt(void)
77 regcontext_t *REGS = saved_regcontext;
78 int irql;
80 if (R_EFLAGS & PSL_VIF) {
81 for (irql = 0; irql < 8; irql++)
82 if (Irqs[irql].within && int_allowed(irql)) {
83 Irqs[irql].within = 0;
84 if (Irqs[irql].eoir)
85 Irqs[irql].eoir(Irqs[irql].arg);
88 for (irql = 0; irql < 8; irql++)
89 if (Irqs[irql].pending && int_allowed(irql)) {
90 Irqs[irql].pending = 0;
91 hardint(irql);
92 break;
95 set_vip();
98 void
99 send_eoi(void)
101 if (Irql >= 8)
102 return;
104 Irqs[Irql].busy = 0;
106 while (++Irql < 8)
107 if (Irqs [Irql].busy)
108 break;
110 resume_interrupt();
114 ** Cause a hardware interrupt to happen immediately after
115 ** we return to vm86 mode
117 void
118 hardint(int irql)
120 regcontext_t *REGS = saved_regcontext;
121 u_long vec = ivec[8 + irql];
124 ** if we're dead, or there's no vector, or the saved registers
125 ** are invalid
127 if (dead || !saved_valid || vec == 0)
128 return;
131 ** if the vector points into the BIOS, or the handler at the
132 ** other end is just an IRET, don't bother
134 if ((vec >> 16) == 0xf000 || *(u_char *)VECPTR(vec) == 0xcf)
135 return;
137 if (!int_allowed(irql)) {
138 Irqs[irql].pending = 1;
139 return;
142 if ((R_EFLAGS & PSL_VIF) == 0) {
143 Irqs[irql].pending = 1;
144 R_EFLAGS |= PSL_VIP;
145 return;
148 debug(D_TRAPS | (8 + irql), "Int%02x [%04lx:%04lx]\n",
149 8 + irql, vec >> 16, vec & 0xffff);
151 Irql = irql;
152 Irqs[Irql].busy = 1;
153 if (Irqs[Irql].eoir)
154 Irqs[Irql].within = 1;
156 PUSH((R_FLAGS & ~PSL_I) | (R_EFLAGS & PSL_VIF ? PSL_I : 0), REGS);
157 PUSH(R_CS, REGS);
158 PUSH(R_IP, REGS);
159 R_EFLAGS &= ~PSL_VIF; /* XXX disable interrupts */
160 PUTVEC(R_CS, R_IP, vec);
163 void
164 unpend(int irql)
166 if (!Irqs[irql].pending)
167 return;
168 Irqs[irql].pending = 0;
169 set_vip();
172 static unsigned char
173 irqc_in(int port __unused)
175 return 0x60; /* What should be here? */
178 static void
179 irqc_out(int port __unused, unsigned char val)
181 if (val == 0x20)
182 send_eoi();
185 static unsigned char
186 imr_in(int port __unused)
188 return IM;
191 static void
192 imr_out(int port __unused, unsigned char val)
194 IM = val;
195 resume_interrupt();
199 ** Cause a software interrupt to happen immediately after we
200 ** return to vm86 mode
202 void
203 softint(int intnum)
205 regcontext_t *REGS = saved_regcontext;
206 u_long vec = ivec[intnum];
209 ** if we're dead, or there's no vector or the saved registers are
210 ** invalid
212 if (dead || !saved_valid || vec == 0)
213 return;
216 ** if the vector points into the BIOS, or the handler at the other
217 ** end is just an IRET, don't bother.
219 if ((vec >> 16) == 0xf000 || *(u_char *)VECPTR(vec) == 0xcf)
220 return;
222 debug(D_TRAPS | intnum, "INT %02x [%04lx:%04lx]\n",
223 intnum, vec >> 16, vec & 0xffff);
225 PUSH((R_FLAGS & ~PSL_I) | (R_EFLAGS & PSL_VIF ? PSL_I : 0), REGS);
226 PUSH(R_CS, REGS);
227 PUSH(R_IP, REGS);
228 R_EFLAGS &= ~PSL_VIF; /* XXX disable interrupts? */
229 PUTVEC(R_CS, R_IP, vec);
232 void
233 init_ints(void)
235 int i;
237 for (i = 0; i < 8; i++) {
238 Irqs[i].busy = 0;
239 Irqs[i].pending = 0;
240 Irqs[i].within = 0;
243 IM = 0x00;
244 Irql = 8;
246 define_input_port_handler(0x20, irqc_in);
247 define_output_port_handler(0x20, irqc_out);
248 define_input_port_handler(0x21, imr_in);
249 define_output_port_handler(0x21, imr_out);