summaryrefslogtreecommitdiffstats
path: root/usr.bin/doscmd/int.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/int.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/int.c')
-rw-r--r--usr.bin/doscmd/int.c139
1 files changed, 139 insertions, 0 deletions
diff --git a/usr.bin/doscmd/int.c b/usr.bin/doscmd/int.c
new file mode 100644
index 0000000..2385f56
--- /dev/null
+++ b/usr.bin/doscmd/int.c
@@ -0,0 +1,139 @@
+/*
+** No copyright?!
+**
+** $Id: int.c,v 1.4 1997/03/18 02:36:56 msmith Exp $
+*/
+#include "doscmd.h"
+
+/*
+** Cause a software interrupt to happen immediately after we
+** return to vm86 mode
+*/
+void
+softint(int intnum)
+{
+ regcontext_t *REGS = saved_regcontext;
+ u_long vec = ivec[intnum];
+
+ /*
+ ** if we're dead, or there's no vector or the saved registers are
+ ** invalid
+ */
+ if (dead || !saved_valid || vec == 0)
+ return;
+
+ /*
+ ** if the vector points into the BIOS, or the handler at the other
+ ** end is just an IRET, don't bother.
+ */
+ if ((vec >> 16) == 0xf000 || *(u_char *)VECPTR(vec) == 0xcf)
+ return;
+
+#if 0
+ /*
+ * software interrupts are always taken
+ */
+ if ((R_EFLAGS & PSL_VIF) == 0) {
+ delay_interrupt(intnum, softint);
+ return;
+ }
+#endif
+
+ debug(D_TRAPS|intnum, "Int%x [%04x:%04x]\n",
+ intnum, vec >> 16, vec & 0xffff);
+
+ N_PUSH((R_FLAGS & ~PSL_I) | (R_EFLAGS & PSL_VIF ? PSL_I : 0), REGS);
+ N_PUSH(R_CS, REGS);
+ N_PUSH(R_IP, REGS);
+#if 1
+ R_EFLAGS &= ~PSL_VIF; /* XXX disable interrupts? */
+#else
+ R_EFLAGS |= PSL_VIF;
+#endif
+ N_PUTVEC(R_CS, R_IP, vec);
+}
+
+/*
+** Cause a hardware interrupt to happen immediately after
+** we return to vm86 mode
+*/
+void
+hardint(int intnum)
+{
+ regcontext_t *REGS = saved_regcontext;
+ u_long vec = ivec[intnum];
+
+ /*
+ * XXXXX
+ * We should simulate the IRQ mask in the PIC.
+ */
+
+ /*
+ ** if we're dead, or there's no vector, or the saved registers
+ ** are invalid
+ */
+ if (dead || !saved_valid || vec == 0)
+ return;
+
+ /*
+ ** if the vector points into the BIOS, or the handler at the
+ ** other end is just an IRET, don't bother
+ */
+ if ((vec >> 16) == 0xf000 || *(u_char *)VECPTR(vec) == 0xcf)
+ return;
+
+ if ((R_EFLAGS & PSL_VIF) == 0) {
+ delay_interrupt(intnum, hardint);
+ return;
+ }
+
+ debug(D_TRAPS|intnum, "Int%x [%04x:%04x]\n",
+ intnum, vec >> 16, vec & 0xffff);
+
+ N_PUSH((R_FLAGS & ~PSL_I) | (R_EFLAGS & PSL_VIF ? PSL_I : 0), REGS);
+ N_PUSH(R_CS, REGS);
+ N_PUSH(R_IP, REGS);
+#if 1
+ R_EFLAGS &= ~PSL_VIF; /* XXX disable interrupts */
+#else
+ R_EFLAGS |= PSL_VIF;
+#endif
+ N_PUTVEC(R_CS, R_IP, vec);
+}
+
+typedef void (*foo_t)(int);
+
+void
+resume_interrupt(void)
+{
+ int i;
+ regcontext_t *REGS = saved_regcontext;
+
+ n_pending--;
+ if (n_pending == 0)
+ R_EFLAGS &= ~PSL_VIP;
+
+ for (i = 0; i < 256; i++) {
+ if (pending[i]) {
+ ((foo_t)(pending[i]))(i);
+ pending[i] = 0;
+ break;
+ }
+ }
+}
+
+
+void
+delay_interrupt(int intnum, void (*func)(int))
+{
+ regcontext_t *REGS = saved_regcontext;
+
+#if 0
+printf("DELAY [%x/%d]\n", intnum, n_pending);
+#endif
+ if (pending[intnum] == 0) {
+ pending[intnum] = (u_long)func;
+ n_pending++;
+ }
+ R_EFLAGS |= PSL_VIP;
+}
OpenPOWER on IntegriCloud