home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 December
/
simtel1292_SIMTEL_1292_Walnut_Creek.iso
/
msdos
/
modem
/
async.arc
/
INTCOMM.C
< prev
next >
Wrap
C/C++ Source or Header
|
1986-10-10
|
3KB
|
145 lines
/*M
intcomm - implement common code for interrupt handlers that call
C routines
*/
#include "interrup.h"
int_handler template =
{
#ifndef MPU80186
{ 0x53, /* push bx */
0x06, /* push es */ },
#else
{ 0x60 /* pusha */ },
#endif
{ 0xBB, 0x0000 /* mov bx, seg svc */ },
{ 0x8E, 0xC3 /* mov es,bx */ },
{ 0xBB,0x0000 /* mov bx,offset svc */ },
{ 0x9A,0x0000,0x0000/* call common far */ },
#ifndef MPU80186
{ 0x07, /* pop es */
0x5B, /* pop bx */ },
#else
{ 0x61 /* popa */ },
#endif
0xCF, /* iret */
0x0000, /* old_offset */
0x0000, /* old_segment */
0x0000, /* new_offset */
0x0000 /* new_segment */
};
int_handler *
setup_handler(int_num,handler,chain_int)
int int_num; /* number of the interrupt to steal */
void (*handler)(); /* C function to attach to interrupt */
int chain_int; /* 1 if you're supposed to call old service
when you're done
0 if you're supposed to replace it */
{
union
{
struct
{
unsigned offset,segment;
} parts;
long vector;
} int_vector;
extern long get_int();
extern void set_int();
extern int _dsval, _csval;
register int_handler *new_handler;
void *malloc();
void common(); /* common interrupt handler code */
/* allocate a new handler */
if (NULL == (new_handler = malloc(sizeof(int_handler))))
return NULL;
/* copy template via structure assignment */
*new_handler = template;
/* initialize the mov bx,seg service instruction */
new_handler->esfix.immed_data =
#ifdef LONGPTR
segment(new_handler);
#else
_dsval;
#endif
/* initialize the mov bx, offset service instruction */
new_handler->svctobx.immed_data = offset(&(new_handler->new_offset));
/* initialize the call far common instruction */
new_handler->func_call.offset = offset(common);
new_handler->func_call.segment =
#ifdef FARPROC
segment(common);
#else
_csval;
#endif
/* initialize the vector field of new_handler structure */
new_handler->new_offset = offset(handler);
new_handler->new_segment =
#ifdef FARPROC
segment(handler);
#else
_csval;
#endif
int_vector.vector = get_int(int_num);
/* save old segment */
new_handler->old_offset = int_vector.parts.offset;
new_handler->old_segment = int_vector.parts.segment;
/* if we're supposed to chain to old interrupt call, change iret to
call far. Since I store old vector right after iret, what could be
simpler ?
*/
if (chain_int)
new_handler->iret = 0xEA; /* jmp inter-segment direct */
/* set up new vector */
set_int(int_num,offset(new_handler),segment(new_handler));
return new_handler;
}
restore_handler(int_num,handler)
int int_num;
int_handler *handler;
{
extern void set_int();
set_int(int_num,handler->old_offset,handler->old_segment);
free(handler);
}
/*
* offset and segment used to isolate pointer components
*/
static offset(ptr)
#ifdef LONGPTR
unsigned long ptr;
{
return (int)(0x0000FFFF & ptr);
}
#else
unsigned ptr;
{
return ptr;
}
#endif
static segment(ptr)
#ifdef LONGPTR
unsigned long ptr;
{
return (int) (0x0000FFFF & (ptr >> 16));
}
#else
{
extern int _dsval;
return _dsval;
}
#endif