Thread overview
Function addressing in dosX Q.
Jun 17, 2002
E. Trelmar
Jun 17, 2002
Jan Knepper
Jun 17, 2002
E. Trelmar
Jun 17, 2002
Jan Knepper
Jun 17, 2002
roland
Jun 21, 2002
E. Trelmar
Jun 18, 2002
Heinz Saathoff
June 17, 2002
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;
}


June 17, 2002
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;
> }



June 17, 2002
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.
(Code segment removed for space considerations)

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?


June 17, 2002
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.
> (Code segment removed for space considerations)
>
> 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?

June 17, 2002
"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;
> }
June 18, 2002
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
June 21, 2002
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.