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/int.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/int.c')
-rw-r--r-- | usr.bin/doscmd/int.c | 139 |
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; +} |