Mail Archives: djgpp/2001/11/02/12:23:45
On Fri, 02 Nov 2001 11:11:21 +0200, Eli Zaretskii <eliz AT is DOT elta DOT co DOT il> wrote:
> Please post the important parts here. In particular, the code which
> installs the interrupt handler is the crucial detail.
>
> I suggest to begin with the variant which installs protected-mode
> handler, since it should be the most straightforward one.
>
> In case you didn't already, please read section 18.9 of the DJGPP FAQ
> list, perhaps it will give some clues.
Oh yes, many times have I read that. :)
Below are relevant portions of code for the installation of protected mode
interrupt handler for rs232 port 1. The uart is setup via an assembly call
program, the ISR is in assembly. Both of these routines are in a large
assembly block of code containing other utilities to be used later and
locked with 'lock initcom'. The data section for all of this is locked via
the 'lock data_area' line.
In the ISR I am setting the newb flag byte to 1 and passing back to C the
byte input from the uart in rsbyte. For test I set the newb byte to 1 at
the beginning of the ISR just to see if the program was going to the ISR and
it isn't. I've probably missed something here, but am not seeing it.
Both setup and ISR routines in assembly are very complete and work fine in
the real mode. It is as if the vectors for the handler aren't actually being
written for the new handler address. Perhaps I'm missing some step or have
coded this incorrectly. The stack setup was copied verbatim from Jeronimo's
link, but not sure I understand if it is correct or not.
Most of the material came from a page by Frederico Jeronimo, a link on the
djgpp site.
-------------- the C program:
#define STACK_SIZE 1024
extern void handler_wrapper(), handler_wrapper_end();
extern void rs232_handler(), rs232_handler_end();
extern void data_area(), data_area_end();
extern void initcom(short,short,short), initcom_end();
extern void bdrate(short);
short newb, rsbyte;
long handler;
unsigned char *stack;
int main()
{
unsigned char ch;
char eljs[]="T";
short brate = 6, cardtype=31, numbrs = 0xf, portn = 1;
__dpmi_paddr newhandler, oldhandler;
stack = (char *)malloc(STACK_SIZE);
handler = (long)rs232_handler;
if (stack){
_go32_dpmi_lock_data(stack,STACK_SIZE);
_go32_dpmi_lock_data(&stack, sizeof(stack));
stack += STACK_SIZE - 32;
}
/* coded for serial port 1, which is 0x3f8 with IRQ 4 */
__dpmi_get_protected_mode_interrupt_vector(4,&oldhandler);
newhandler.selector = _my_cs();
newhandler.offset32 = (long)handler_wrapper;
newb = 0;
rsbyte = 0;
LOCK_VARIABLE(newb);
LOCK_VARIABLE(rsbyte);
LOCK_VARIABLE(handler);
LOCK_FUNCTION(initcom);
LOCK_FUNCTION(data_area);
LOCK_FUNCTION(handler_wrapper);
printf("\nInstalling the handlers using the NASM assembler\n");
__dpmi_set_protected_mode_interrupt_vector(4,&newhandler);
/* initcom is an assembly routine to setup the uart, I passed back for
checking in newb and rsbyte two of the uart register contents (those being
required for interrupts) and feel the uart is setup correctly. */
initcom(cardtype,numbrs,portn);
printf("The newb is %d\n",newb);
printf("The rsbyte is %d\n",rsbyte);
/* remove the mask for the interrupt for serial port 1 - start */
ch = inportb(0x21);
outportb(0x21,ch & 0x0ef);
/* strt232(); an assembly call to do the same as above (have tried this)*/
newb=1;
rsbyte = 65;
while (!kbhit()){
if (newb == 1){
printf("data received - ");
eljs[0] = rsbyte;
printf("%s\n",eljs);
newb = 0;
}
}
/* mask the interrupt bit for serial port 1 - stop */
ch = inportb(0x21);
outportb(0x21,ch | 0x10);
/* end232(); an assembly call to do the same as above */
__dpmi_set_protected_mode_interrupt_vector(4,&oldhandler);
/* One final step is required. We should always unlock everything that
was locked. */
UNLOCK_VARIABLE(newb);
UNLOCK_VARIABLE(rsbyte);
UNLOCK_VARIABLE(handler);
UNLOCK_FUNCTION(initcom);
UNLOCK_FUNCTION(data_area);
UNLOCK_FUNCTION(handler_wrapper);
}
-------------- the NASM wrapper:
[BITS 32]
extern ___djgpp_ds_alias
extern _stack
extern _rs232_handler
extern _handler
[SECTION .text]
align 4
global _handler_wrapper
_handler_wrapper:
push word ds
push word es
push word fs
push word gs
pusha
mov word ax, [___djgpp_ds_alias] ; Set up a valid selector
mov word ds, ax
mov word es, ax
mov word fs, ax
mov word gs, ax
lea long ebx, [_stack]
cmp long[ebx],0
jz over
mov long ecx,esp
mov long edx,ss
mov long esp,[ebx]
mov word ss,eax
mov long [ebx],0
push long edx
push long ecx
push long ebx
cld
mov long eax, _handler
call [eax]
cli
pop long ebx ; Pop old stack
pop long ecx
pop long edx
mov long [ebx], esp ; Restore old stack
mov word ss, edx
mov long esp, ecx
over:
popa
pop word gs
pop word fs
pop word es
pop word ds
sti
iret
global _handler_wrapper_end
_handler_wrapper_end:
ret
--
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~ Edwin Johnson ....... elj AT shreve DOT net ~
~ http://www.shreve.net/~elj ~
~ ~
~ "Once you have flown, you will walk the ~
~ earth with your eyes turned skyward, ~
~ for there you have been, there you long ~
~ to return." -- da Vinci ~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- Raw text -