delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/2003/09/03/12:45:43

From: "Don Duttweiler" <duttweiler AT stanfordalumni DOT org>
Newsgroups: comp.os.msdos.djgpp
Subject: Two real address in __dpmi_int call
Lines: 159
X-Priority: 3
X-MSMail-Priority: Normal
X-Newsreader: Microsoft Outlook Express 6.00.2800.1106
X-MimeOLE: Produced By Microsoft MimeOLE V6.00.2800.1106
Message-ID: <XTo5b.25699$S_.24410@fed1read01>
Date: Wed, 3 Sep 2003 09:44:40 -0700
NNTP-Posting-Host: 68.7.59.216
X-Complaints-To: abuse AT cox DOT net
X-Trace: fed1read01 1062607479 68.7.59.216 (Wed, 03 Sep 2003 12:44:39 EDT)
NNTP-Posting-Date: Wed, 03 Sep 2003 12:44:39 EDT
Organization: Cox Communications
To: djgpp AT delorie DOT com
DJ-Gateway: from newsgroup comp.os.msdos.djgpp
Reply-To: djgpp AT delorie DOT com

I can not get the extended BIOS read interrupt (function 0x42 under
interrupt 0x13) to work under DJGPP.  This interrupt is a bit more of
a mess than usual because two real-mode addresses are involved.  One
is the usual offset and segment of a structure passed to the interrupt
via __dpmi_regs.  But for this interrupt, this structure itself contains
an offset and segment for a buffer that is used for storing what is read
from disk.

My basic approach for this has been to use one region of __tb for
passing the structure to the real mode interrupt and another region
of __tb for the disk read buffer.  It doesn't work.  Whether executing
from a DOS box or executing in DOS mode, the program
hangs on the call to __dpmi_int.

Two program listings are below.  The one titled realmode.c I compile
with Microsoft C 6.0 (a 16 bit compiler) and it runs fine.  (The
interrupt itself does require a newer BIOS with LBA extensions.)

The one titled dpmimode.c is my translation of realmode.c to a protected
mode program to compile under DJGPP.  As noted above it hangs
on the call to __dpmi_int.  I've tried zeroing some of the unused registers
in __dpmi_regs as suggested in section 18.3 of the FAQ.  That doesn't
seem to make any difference.  I've also tried using
__dpmi_allocate_dos_memory
to get some real-mode memory for the read buffer, but that also doesn't
seem to help.  I'm running Win 98 SE and compiling with
GCC 3.0.2, but doubt that is of any consequence for this.

Does anyone have any ideas on how to fix things?  Thanks.

Don Duttweiler
duttweilerATstanfordalumniDOTorg

******** realmode.c
*********************************************************

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dos.h>
#include <malloc.h>

int main(int argc,char** argv) {
  char far * buffer;
  union REGS inregs, outregs;
  struct SREGS segregs;
  unsigned char mysize;
  int drive;
  #pragma pack(1)
  struct {
    unsigned char mysize;
    unsigned char reserved;
    unsigned short blockCount;
    unsigned short bufAdrOffset;
    unsigned short bufAdrSeg;
    unsigned long lbaLow;
    unsigned long lbaHigh;
  } bufAdr, far *pbufAdr;
  #pragma pack()

  if(argc!=1) {
    fprintf(stderr,"Unexpected count: %d in %s",argc,argv[0]);
    exit(1);
  }

  mysize = sizeof(bufAdr);
  if(mysize != 16) { fprintf(stderr,"Unexpected size: %d",mysize);
exit(1); }

  buffer = _fmalloc(512);
  drive = 128;

  bufAdr.mysize = mysize;
  bufAdr.blockCount = 1;
  bufAdr.bufAdrOffset = FP_OFF(buffer);
  bufAdr.bufAdrSeg = FP_SEG(buffer);
  bufAdr.lbaLow = 0;
  bufAdr.lbaHigh = 0;

  pbufAdr = &bufAdr;
  inregs.h.ah = 0x42;
  inregs.h.dl = (char)drive;
  inregs.x.si = FP_OFF(pbufAdr);
  segregs.ds = FP_SEG(pbufAdr);
  int86x(0x13, &inregs, &outregs, &segregs);
  if((outregs.x.cflag == 0) && (outregs.h.ah == 0)) {
    printf("Good execution\n");
  } else {
    printf("Bad execution\n");
  }
  return 0;
}

******** dpmimode.c
**********************************************************

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dos.h>
#include <malloc.h>
#include <dpmi.h>
#include <go32.h>

int main(int argc,char **argv) {
  __dpmi_regs dreg;
  char* buffer;
  int cflag,drive;
  unsigned char mysize;
  struct {
    unsigned char mysize;
    unsigned char reserved;
    unsigned short blockCount;
    unsigned short bufAdrOffset;
    unsigned short bufAdrSeg;
    unsigned long lbaLow;
    unsigned long lbaHigh;
  } __attribute__ ((packed)) bufAdr;


  if(argc!=1) {
    fprintf(stderr,"Unexpected count %d in %s",argc,argv[0]);
    exit(1);
  }

  mysize = sizeof(bufAdr);
  if(mysize != 16) { fprintf(stderr,"Unexpected size: %d",mysize);
exit(1); }

  buffer = malloc(512);

  drive = 128;

  bufAdr.mysize = mysize;
  bufAdr.blockCount = 1;
  bufAdr.bufAdr.fset = __tb & 0x0F;
  bufAdr.bufAdrSeg = (__tb + 1024) >> 4;
  bufAdr.lbaLow = 0;
  bufAdr.lbaHigh = 0;

  dreg.h.ah = 0x42;
  dreg.h.dl = (char)drive;
  dreg.x.si = __tb & 0x0F;
  dreg.x.ds = __tb >> 4;
  dosmemput(&bufAdr,mysize,__tb);
  printf("Calling __dpmi_int\n"); fflush(stdout);
  __dpmi_int(0x13,&dreg);
  printf("Returned __dpmi_int\n"); fflush(stdout);
  cflag = dreg.x.flags & 0x01;
  if((cflag == 0) && (dreg.h.ah == 0)) {
    printf("Good execution\n");
  } else {
    printf("Bad execution\n");
  }
  dosmemget(__tb+1024,512,buffer);
  return 0;
}


- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019