www.digitalmars.com         C & C++   DMDScript  

c++.dos.32-bits - Function addressing in dosX Q.

reply E. Trelmar <E._member pathlink.com> writes:
I'm having a problem correctly accessing linear memory (I think) in passing
segments and offsets to the modified 21h, subfunction 25h series of dos
commands, causing a general protection fault from an illegal segment. I'm not
too familiar with 32 bit coding, and was wondering what mistake I'm making?
If any other bits of code are needed, please tell me and I'll post.

Hopefully the code below I have posted isn't too long yet contains everything:

static void kbdisr();
void keyboardx::kbdisr()
{
_disable();
callback();
_enable();
}
static void (*oldisr)();

keyboardx::keyboardx()
{
static void (*previous_isr)();
union _REGS inregs, outregs;
struct _SREGS segregs;
byte17 = (char *)_x386_zero_base_ptr + 0x00400017;
byte97 = (char *)_x386_zero_base_ptr + 0x00400097;
_disable();
outp(KEY_BUFFER, 0xEE);
if (await_status(0xEE))
keyboard_controller = 8042;
else
keyboard_controller = 8048;
_segread(&segregs);
inregs.x.ax = 0x2502;
inregs.h.cl = KEYBOARD_INT;
intdosx(&inregs, &outregs, &segregs);
previous_isr = (void *)(segregs.es + outregs.e.ebx);
if (previous_isr != &kbdisr)
{
oldisr = previous_isr;
callback = buffercall; // External keyboard handler function
_segread(&segregs);
inregs.x.ax = 0x2504;
inregs.h.cl = KEYBOARD_INT;
inregs.e.edx = 0; /* I put no offset for the address */
segregs.ds = (long)&kbdisr; /* And used only the function's address (The same
code is generated with or without the memory offset operand &) */
intdosx(&inregs, &outregs, &segregs); /* Interrupt 0Dh (Hard Disk Access),
General Protection Fault (possible illegal segment) on line below*/
}
rprs = MAXBUF - 1; // Buffer index for keyboard
_enable();
cps_lck = *byte97 & 4;
nm_lck = *byte97 & 2;
scrll_lck = *byte97 & 1;
}
Jun 17 2002
next sibling parent reply Jan Knepper <jan smartsoft.cc> writes:
Here, some functions I developed years ago to access 'base' memory from
'extended'
memory in DOSX mode. I used these to use the Btrieve DOS engine from a DOSX
program.

static void             _x386_memcpy_ff ( void *, void _far *, size_t );
static void             _x386_memcpy_tf ( void _far *, void *, size_t );
static void             _x386_memset_f  ( void _far *, int, size_t );

[snip]

   /*
    * Now make a protected mode pointer to the allocated real mode memory.
    * Clear the real mode memory and initialize it with the necessary stuff.
    */

   rmidb   = ( RMIDB _far * ) _x386_mk_protected_ptr ( abs_addr );

   _x386_memset_f ( rmidb, 0, sizeof ( RMIDB ) );

   rmidb -> bp.DataBufP  = ( long ) ( ( ( long ) DOSBuffSeg << 16 ) + offsetof (
RMIDB, db  )      );
   rmidb -> bp.PosBlockP = ( long ) ( ( ( long ) DOSBuffSeg << 16 ) + offsetof (
RMIDB, pos ) + 38 );
   rmidb -> bp.FCBBuffP  = ( long ) ( ( ( long ) DOSBuffSeg << 16 ) + offsetof (
RMIDB, pos )      );
   rmidb -> bp.KeyBufP   = ( long ) ( ( ( long ) DOSBuffSeg << 16 ) + offsetof (
RMIDB, kb  )      );
   rmidb -> bp.bswP      = ( long ) ( ( ( long ) DOSBuffSeg << 16 ) + offsetof (
RMIDB, bsw )      );
   rmidb -> bp.KeyLen    = KEYBUF;
   rmidb -> bp.XFaceID   = VARIABLE_ID;

[snip]

   /*
    * Copy all the parameters to the Real Mode memory area.
    */

   rmidb -> bp.OpCode  = operation;
   rmidb -> bp.BufLen  = *dataLength;
   rmidb -> bp.KeyNum  = ( BTI_BYTE ) keyNumber;

   _x386_memcpy_tf ( rmidb -> db , dataBuffer, *dataLength );
   _x386_memcpy_tf ( rmidb -> kb , keyBuffer , KEYBUF  );
   _x386_memcpy_tf ( rmidb -> pos, posBlock  , SZPOS   );

   /*
    * Make call to the Btrieve Record Manager.
    * Btrieve parameter block is expected in DS:DX.
    */

   sregs.ds  = DOSBuffSeg;
   regs.x.dx = 0;

   int86x_real ( BTR_INTRPT, &regs, &regs, &sregs );

   /*
    * Now copy everything back to the application buffers.
    */

   *dataLength = rmidb -> bp.BufLen;

   _x386_memcpy_ff ( dataBuffer, rmidb -> db , *dataLength );
   _x386_memcpy_ff ( keyBuffer , rmidb -> kb , KEYBUF      );
   _x386_memcpy_ff ( posBlock  , rmidb -> pos, SZPOS       );

[snip]

    _x386_free_protected_ptr ( rmidb );

[snip]

static void  _x386_memcpy_ff ( void  *to, void _far  *from, size_t  size )
{
   unsigned char        *_to   = to;
   unsigned char _far   *_from = from;

   for ( size_t  i = 0 ; i < size ; i++ )
      *_to++ = *_from++;
}



static void  _x386_memcpy_tf ( void _far  *to, void  *from, size_t  size )
{
   unsigned char _far   *_to   = to;
   unsigned char        *_from = from;

   for ( size_t  i = 0 ; i < size ; i++ )
      *_to++ = *_from++;
}



static void  _x386_memset_f ( void _far  *to, int  b, size_t  size )
{
   unsigned char _far   *_to   = to;

   for ( size_t  i = 0 ; i < size ; i++ )
      *_to++ = b;
}



"E. Trelmar" wrote:

 I'm having a problem correctly accessing linear memory (I think) in passing
 segments and offsets to the modified 21h, subfunction 25h series of dos
 commands, causing a general protection fault from an illegal segment. I'm not
 too familiar with 32 bit coding, and was wondering what mistake I'm making?
 If any other bits of code are needed, please tell me and I'll post.

 Hopefully the code below I have posted isn't too long yet contains everything:

 static void kbdisr();
 void keyboardx::kbdisr()
 {
 _disable();
 callback();
 _enable();
 }
 static void (*oldisr)();

 keyboardx::keyboardx()
 {
 static void (*previous_isr)();
 union _REGS inregs, outregs;
 struct _SREGS segregs;
 byte17 = (char *)_x386_zero_base_ptr + 0x00400017;
 byte97 = (char *)_x386_zero_base_ptr + 0x00400097;
 _disable();
 outp(KEY_BUFFER, 0xEE);
 if (await_status(0xEE))
 keyboard_controller = 8042;
 else
 keyboard_controller = 8048;
 _segread(&segregs);
 inregs.x.ax = 0x2502;
 inregs.h.cl = KEYBOARD_INT;
 intdosx(&inregs, &outregs, &segregs);
 previous_isr = (void *)(segregs.es + outregs.e.ebx);
 if (previous_isr != &kbdisr)
 {
 oldisr = previous_isr;
 callback = buffercall; // External keyboard handler function
 _segread(&segregs);
 inregs.x.ax = 0x2504;
 inregs.h.cl = KEYBOARD_INT;
 inregs.e.edx = 0; /* I put no offset for the address */
 segregs.ds = (long)&kbdisr; /* And used only the function's address (The same
 code is generated with or without the memory offset operand &) */
 intdosx(&inregs, &outregs, &segregs); /* Interrupt 0Dh (Hard Disk Access),
 General Protection Fault (possible illegal segment) on line below*/
 }
 rprs = MAXBUF - 1; // Buffer index for keyboard
 _enable();
 cps_lck = *byte97 & 4;
 nm_lck = *byte97 & 2;
 scrll_lck = *byte97 & 1;
 }

Jun 17 2002
parent reply E. Trelmar <E._member pathlink.com> writes:
In article <3D0E1FFC.3ECEE7AE smartsoft.cc>, Jan Knepper says...
Here, some functions I developed years ago to access 'base' memory from
'extended'
memory in DOSX mode. I used these to use the Btrieve DOS engine from a DOSX
program.

I'm a bit confused, how will accessing base memory with far pointers help me with my problem in 32 bit coding when trying to pass a protected mode address to the 32 bit version of int 21h, subfunction 25h? Could you possibly elucidate?
Jun 17 2002
parent Jan Knepper <jan smartsoft.cc> writes:
Sorry, I didn't read your message to well obviously. I thought you have problem
accessing base memory.
Roland might be able to help you with what you want to do. (If he has the time).

Jan



"E. Trelmar" wrote:

 In article <3D0E1FFC.3ECEE7AE smartsoft.cc>, Jan Knepper says...
Here, some functions I developed years ago to access 'base' memory from
'extended'
memory in DOSX mode. I used these to use the Btrieve DOS engine from a DOSX
program.

I'm a bit confused, how will accessing base memory with far pointers help me with my problem in 32 bit coding when trying to pass a protected mode address to the 32 bit version of int 21h, subfunction 25h? Could you possibly elucidate?

Jun 17 2002
prev sibling next sibling parent reply roland <--nancyetroland free.fr> writes:
"E. Trelmar" a écrit :
 
 I'm having a problem correctly accessing linear memory (I think) in passing
 segments and offsets to the modified 21h, subfunction 25h series of dos
 commands, causing a general protection fault from an illegal segment. I'm not
 too familiar with 32 bit coding, and was wondering what mistake I'm making?
 If any other bits of code are needed, please tell me and I'll post.
 

To trap an interrupt i use to ... use int_intercept / int_restore. It's fast and works fine with all interrupt i trapped .. except keyboard interrupt (9) ! Too bad. I don't know why. I didn't try again since a while. So you may try using int_intercept / int_restore functions. If it works for you, please let me know. Good luck dealing with 8042. I use to work with chips, but this one really gives me a lot of trouble. At least with the keyboard chanel. With the PS/2 one it was ok. sorry, can't help more ciao roland
 Hopefully the code below I have posted isn't too long yet contains everything:
 
 static void kbdisr();
 void keyboardx::kbdisr()
 {
 _disable();
 callback();
 _enable();
 }
 static void (*oldisr)();
 
 keyboardx::keyboardx()
 {
 static void (*previous_isr)();
 union _REGS inregs, outregs;
 struct _SREGS segregs;
 byte17 = (char *)_x386_zero_base_ptr + 0x00400017;
 byte97 = (char *)_x386_zero_base_ptr + 0x00400097;
 _disable();
 outp(KEY_BUFFER, 0xEE);
 if (await_status(0xEE))
 keyboard_controller = 8042;
 else
 keyboard_controller = 8048;
 _segread(&segregs);
 inregs.x.ax = 0x2502;
 inregs.h.cl = KEYBOARD_INT;
 intdosx(&inregs, &outregs, &segregs);
 previous_isr = (void *)(segregs.es + outregs.e.ebx);
 if (previous_isr != &kbdisr)
 {
 oldisr = previous_isr;
 callback = buffercall; // External keyboard handler function
 _segread(&segregs);
 inregs.x.ax = 0x2504;
 inregs.h.cl = KEYBOARD_INT;
 inregs.e.edx = 0; /* I put no offset for the address */
 segregs.ds = (long)&kbdisr; /* And used only the function's address (The same
 code is generated with or without the memory offset operand &) */
 intdosx(&inregs, &outregs, &segregs); /* Interrupt 0Dh (Hard Disk Access),
 General Protection Fault (possible illegal segment) on line below*/
 }
 rprs = MAXBUF - 1; // Buffer index for keyboard
 _enable();
 cps_lck = *byte97 & 4;
 nm_lck = *byte97 & 2;
 scrll_lck = *byte97 & 1;
 }

Jun 17 2002
parent E. Trelmar <E._member pathlink.com> writes:
Thanks for the suggestion roland, the int_intercept/int_restore worked fine for
keyboard interrupt(0x9). Also, to Heinz Saatho, thanks for the side comment
about the byte addressing, almost forgot about that.
Jun 21 2002
prev sibling parent Heinz Saathoff <hsaat bre.ipnet.de> writes:
E. Trelmar schrieb...
 keyboardx::keyboardx()
 {
 static void (*previous_isr)();
 union _REGS inregs, outregs;
 struct _SREGS segregs;
 byte17 = (char *)_x386_zero_base_ptr + 0x00400017;
 byte97 = (char *)_x386_zero_base_ptr + 0x00400097;

Without answering to the rest (eg. callback from real-mode to protected mode the above address calculation must be changed to byte17 = (char *)_x386_zero_base_ptr + 0x417; byte97 = (char *)_x386_zero_base_ptr + 0x497; to form a linear address to the bios area. Remember that the notation seg:ofs in real mode forms the address (seg<<4)+ofs Regards, Heinz
Jun 17 2002