Mail Archives: djgpp/1993/03/14/13:28:49
My impression is that, if I want to write an interrupt handler routine for
use in a DJGPP program, one method is to write it as a real-mode handler
(using, say, Borland C++) and add it to GO32. Can anyone give me some
pointers as to . . . well . . . how? I know how to write an interrupt
handler for real mode, but I'm not sure about where to add it to GO32's
source, what to watch for, and all that.
Hook it in the file exphdlr.c. There is a function with a switch ...
case construct that gets called when an interrupt occurs in protected
mode. You will need to modify it so that go32 doesn't abort when it
receives your interrupt. The easiest thing would be to install your
handler as a real mode interrupt handler so that it gets called when
an interrupt occurs in real mode and put an int86x(...) call in
exphdlr.c so that it gets called when switched from protected mode.
This next question goes off the deep end, I know . . . Is it possible
using the above method (or, heck, any method) for my interrupt handler to
call a protected mode routine written using DJGPP (or even GAS)?
This is more difficult. You need to add a callback system to go32,
modify the protected mode interrupt table (IDT). The idea is as
follows :
1- Interrupt received while in protected mode :
Just modify the protected mode (PM) IDT so that your PM
handler gets called
2- Interrupt received while in real mode (2 ways to do it) :
A- Your handler is not critical and can wait for the system call to
finish executing :
- Use the function push32 to push the current EIP, CS, EFLAGS
on the PM stack (Look at file control.c).
- set EIP = your PM handler
- Resume execution
When go32 will switch back to PM, it will start executing your
handler. When it encounters an IRET instruction it will switch
back where it was before (Look at the 386 reference in order to
know in what order to push the arguments on the stack).
B- Your handler is critical and needs to be called immediately :
- Create a function like the one in mswitch.asm, but instead
of jumping to a_tss after you switch to PM, issue an INT
call.
switch to PM
call PM handler, using INT #
switch back to real mode
return and resume execution
You need to be careful in your PM handler not to issue any
system call. Go32 is not reentrant, and system calls that
communicate data between PM and RM use a unique buffer. You
either need to save it each time or make sure you don't use
any call that modifies the data in that buffer. Failing to
do so will make you end up with trah in your buffer or fail
your system call when you resume execution in RM.
You will need to create tables to keep track of what to
call, when it is running so you don't call your handler
twice,...
This is a simplified version of what DPMI does. A complete
implementation might allocate a fixed number of descriptors
(callbacks) in the GDT (16 for the DPMI I think). These
callback switch you between modes when you receive
interrupts.
Perhaps it will be much easier to write interrupt handlers as
standalone resident programs the way the async library is written. At
least it will continue to work and might keep a log of interrupts you
receive when you shell out of go32 to execute a dos program. In that
way you will not loose data or interrupts, you will just need to
process the log.
Otherwise expect huge difficulties while debugging (ie nightmares),
and the gratitude of many persons if manage to make it work. You might
also want to read the Intel 386 programmer's reference manual before
starting.
Good luck,
Regards,
Rami
- Raw text -