ftp.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/2011/03/16/19:30:10

X-Authentication-Warning: delorie.com: mail set sender to djgpp-bounces using -f
From: Jim Michaels <jmichae3 AT yahoo DOT com>
Newsgroups: comp.os.msdos.djgpp
Subject: Re: csdpmi7 not working on virtualbox, how use dosmemget with seg ofs
from int21h?
Date: Wed, 16 Mar 2011 16:16:47 -0700 (PDT)
Organization: http://groups.google.com
Lines: 320
Message-ID: <50f38a5d-a391-45e7-a039-14932c9134d8@11g2000prf.googlegroups.com>
References: <39cdc18e-eccb-4213-b896-db3be020702e AT w9g2000prg DOT googlegroups DOT com>
<iknmth$1lb$1 AT speranza DOT aioe DOT org> <3e035797-6b8e-4106-bd29-98e87a9cc121 AT a21g2000prj DOT googlegroups DOT com>
<E1Pz5o6-0001qv-4s AT fencepost DOT gnu DOT org> <428d9bd6-efc5-4f66-bab3-961a0c4598f9 AT f31g2000pri DOT googlegroups DOT com>
<E1PzO3K-0007xl-Bg AT fencepost DOT gnu DOT org> <42d13cb8-adf4-4a86-9cf2-012d0929fb4c AT q40g2000prh DOT googlegroups DOT com>
<E1PzRg3-0006F7-Fj AT fencepost DOT gnu DOT org>
NNTP-Posting-Host: 24.21.90.47
Mime-Version: 1.0
X-Trace: posting.google.com 1300317408 26235 127.0.0.1 (16 Mar 2011 23:16:48 GMT)
X-Complaints-To: groups-abuse AT google DOT com
NNTP-Posting-Date: Wed, 16 Mar 2011 23:16:48 +0000 (UTC)
Complaints-To: groups-abuse AT google DOT com
Injection-Info: 11g2000prf.googlegroups.com; posting-host=24.21.90.47; posting-account=05hOMwoAAAB6R8xtiQKzEljSMzgOhVF1
User-Agent: G2/1.0
X-HTTP-UserAgent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.15)
Gecko/20110303 Firefox/3.6.15 ( .NET CLR 3.5.30729),gzip(gfe)
Bytes: 13718
To: djgpp AT delorie DOT com
DJ-Gateway: from newsgroup comp.os.msdos.djgpp
Reply-To: djgpp AT delorie DOT com

On Mar 15, 3:40=A0am, Eli Zaretskii <e DOT  DOT  DOT  AT gnu DOT org> wrote:
> > From: Jim Michaels <jmich DOT  DOT  DOT  AT yahoo DOT com>
> > Newsgroups: comp.os.msdos.djgpp
> > Date: Tue, 15 Mar 2011 00:37:06 -0700 (PDT)
> > > dosmemget(adr, sizeof(extFAT32FreeSpaceStructure), pds);
>
> > > (assuming `pds' is correct, and you remove `wastedspace' from the
> > > structure, because it makes you fetch data beyond what DOS fills in).
>
> > > Or you could use __tb+STRUCT_OFS instead of `adr', because my reading
> > > of RBIL is that DOS fills the buffer whose address you passed to it i=
n
> > > ES:DI when you called __dpmi_int. Per the FAQ, you should have put
> > > the segment and offset of __tb in ES:DI before invoking __dpmi_int, s=
o
> > > the buffer filled by DOS is in the transfer buffer, and __tb is its
> > > address.
>
> > doesn't work.
>
> What does that mean, exactly? =A0What do you get in the struct after
> __dpmi_int returns? =A0Or does the program crash? =A0Or something else?
>
> > I already check the carry flag, which If I am not
> > mistaken is r.x.flags & 1.
>
> Yes, that's the CF flag. =A0I take it that it's cleared? =A0If so, what i=
s
> the value of r.x.ax after __dpmi_int returns?
>
> > I am not a total idiot.
>
> There was no word "idiot" in my message. =A0People do make honest
> mistakes, you. =A0If you can assume that the basic infrastructure of
> DJGPP doesn't work because "DJ forgot to include" something, I can
> certainly assume that someone who asks trivial questions about
> low-level programming with DJGPP forgot something, too.
>
> > the reason why I padded the struct to size 0x30 was because some of
> > the djgpp dos memory access functions require accessing memory in 16-
> > byte chunks (0x10), or segment size chunks.
>
> Don't. =A0dosmemget doesn't require any such roundups.
>
> > I think I may have to take this problem to the freedos folks and see
> > why 7303h doesn't seem to work on their OS when they are supposed to
> > support it.
>
> > I am still learning. =A0but I need to get solid code so I can say to th=
e
> > freedos folk, "your OS is broken, here's how", or, I can have a
> > working program that works on freedos which uses FAT32 and maybe
> > windows 98.
>
> You could simply ask them if they support 7303. =A0From what you say I'm
> beginning to think they don't. =A0Asking such a question does not need
> any code to show: since this function is not in the standard DOS, and
> is documented in RBIL to be supported only by Windows 9X (not even DOS
> 7 when Windows is not up and running), it's quite reasonable to ask if
> FreeDOS does support it.

7303h *is* supported by freedos however, a very popular DOS, and since
its filesystem is FAT32 (hard disks) as well as FAT16 (hard disks) and
FAT12 (floppies), and as such uses the win95 int21 FAT32 calls.
this is why I am trying to get this working.  it would be very nice if
I didn't have to do this, if DJGPP supported this already in
_dos_getdiskfree() so I wouldn't have to code my own stuff.

when I make the 7303h calls I always get back failure (carry flag set
and ax=3D0x0f), bur first I call 7300h, this seemed to help some.  maybe
I need to install a critical error handler?

the entire code for the program is 3100 lines long, so I think it's
too large to post here.

there is assembler code which works and calls 7300h then 7303h and
works fine and shows 5GB free space on my freedos fat32 partitions.

but when I compile with DJGPP, I always get the value 2.14GB free out
of 2.14GB and 7303h failed because of the carry flag, so my code falls
back to _dos_getdiskfree() which uses int21h function 36h and only
knows about FAT16.

I will show you the major code section which has to do with the calls
I am making.

maybe __dpmi_int() is hooking the software interrupt in a way that
causes errors, or the flags register is not being set correctly after
a software interrupt?







typedef /*long*/ double ld;

#if defined(__DJGPP__)
#define CF 0x01
//#define HANDLE_PRAGMA_PACK_PUSH_POP 1
//#pragma pack(push,1)

struct extFAT32FreeSpaceStructure {
/* 00h	WORD*/uint16_t	struct_size;
/* 02h	WORD*/uint16_t
call_structure_version_ret_actual_structure_version;// (0000h)
/* 04h	DWORD*/uint32_t
number_of_sectors_per_cluster_with_adjustment_for_compression;
/* 08h	DWORD*/uint32_t	number_of_bytes_per_sector;
/* 0Ch	DWORD*/uint32_t	number_of_available_clusters;
/* 10h	DWORD*/uint32_t	total_number_of_clusters_on_the_drive;
/* 14h	DWORD*/uint32_t
number_of_physical_sectors_available_on_the_drive_without_adjustment_for_co=
mpression;
/* 18h	DWORD*/uint32_t
total_number_of_physical_sectors_on_the_drive_without_adjustment_for_compre=
ssion;
/* 1Ch	DWORD*/uint32_t
number_of_available_allocation_units_without_adjustment_for_compression;
/* 20h	DWORD*/uint32_t
total_allocation_units_without_adjustment_for_compression;
/* 24h  8 BYTEs*/uint64_t	reserved;
uint32_t wastedspace;
} __attribute__((packed));
typedef struct extFAT32FreeSpaceStructure extFAT32FreeSpaceStructure;

//#pragma pack(pop)

#endif

char * dirpath[26] =3D {
    "A:\\",  "B:\\",  "C:\\",  "D:\\",  "E:\\",
    "F:\\",  "G:\\",  "H:\\",  "I:\\",  "J:\\",
    "K:\\",  "L:\\",  "M:\\",  "N:\\",  "O:\\",
    "P:\\",  "Q:\\",  "R:\\",  "S:\\",  "T:\\",
    "U:\\",  "V:\\",  "W:\\",  "X:\\",  "Y:\\",
    "Z:\\"
};


bool ShowDrive(unsigned int drive, bool isVerbose) {
#if defined(DEBUG_2)
    printf("ShowDrive(drive=3D%d, verbose=3D%d)\n", drive, isVerbose);//
DEBUG
#endif
    if (drive < a_drive || drive > z_drive) {
        printf("ERROR: ShowDrive(drive=3D%d, verbose=3D%d) invalid drive
number.\n", drive, isVerbose);
        return false;
    }
// 0 is current drive, 1 is a:, 2 is b:, 3 is c:... up to lastdrive.
    ld total, davail;
    int64_t iDAvail, iTotal;
#if defined(__BORLANDC__) || defined(_MSC_VER) || defined
(__MINGW32__)
#elif defined(__DJGPP__)
    struct diskfree_t df;
    extFAT32FreeSpaceStructure *pds =3D (extFAT32FreeSpaceStructure
*)calloc(sizeof(extFAT32FreeSpaceStructure), 1);
#endif
#if defined(__DJGPP__)
/*BUG:	int21h 7303h returns a maximum of 2GB free space even on an
FAT32
	  partition larger than 2GB under some versions of Win95 and Win98,
	  apparently by limiting the number of reported free clusters to no
	  more than 64K -- but only in a DOS window if a TSR has hooked INT
21h
  */



    __dpmi_regs r;
    r.h.dl=3Ddrive;//curent drive
    r.h.cl=3D0x01;//dirty buffers flag
    r.x.ax=3D0x7300;
    pds->struct_size=3D0x30;
    __dpmi_int(0x21, &r);
    if (0x7300!=3Dr.x.ax) {
        //supports fat32.

#if defined(DEBUG_2)
        printf("go32=3D0x%04x, size=3D%d, drive=3D%d,%s
\n",_go32_info_block.linear_address_of_transfer_buffer,sizeof(_go32_info_bl=
ock.linear_address_of_transfer_buffer),drive,dirpath[drive-
a_drive]);//DEBUG
#endif
        pds->call_structure_version_ret_actual_structure_version=3D0;
        dosmemput(pds, sizeof(extFAT32FreeSpaceStructure), __tb +
STRUCT_OFS);
        dosmemput(dirpath[drive-a_drive], strlen(dirpath[drive-
a_drive])+1, __tb + STR_OFS);
        r.x.ax=3D0x7303;
        r.x.cx=3Dsizeof(extFAT32FreeSpaceStructure);//0x30 whereas
before it was 0x2c
        r.x.ds=3D(__tb+STRUCT_OFS)>>4;
        r.x.dx=3D(__tb+STRUCT_OFS)& 0x0f;
        r.x.es=3D(__tb+STR_OFS)>>4;
        r.x.di=3D(__tb+STR_OFS)&0x0f;
        r.x.flags =3D 1; //set carry bit to show error in case there is
no change
        r.x.ss=3D0;
        r.x.sp=3D0;
        __dpmi_int(0x21, &r);
        if (1=3D=3Dr.x.flags & CF
        || (1=3D=3Dr.x.flags & CF && 0=3D=3Dr.h.al)
        ) {
            //error, so try fallback method of using old dos int21h
function 36h _dos_getdiskfree()
            //long long iTotal, iDAvail;

            //for this function, drive starting with 1 is correct.
            if (0=3D=3D_dos_getdiskfree(drive, &df)) { // 0=3Ddefault, 1=3D=
a,
2=3Db...
#if defined(DEBUG_2)
                printf("_dos_getdiskfree() SUCCESS, int21h 7303h
failed#1,flags=3D0x%04x,AX=3D0x%04x\n",r.x.flags,r.x.ax);//DEBUG
#endif
                iDAvail =3Ddf.avail_clusters;         iTotal
=3Ddf.total_clusters;
                iDAvail*=3Ddf.bytes_per_sector;
iTotal*=3Ddf.bytes_per_sector;
                iDAvail*=3Ddf.sectors_per_cluster;
iTotal*=3Ddf.sectors_per_cluster;
                //cout.setf(ios::fixed);
                //cout.unsetf(ios::scientific);
                davail =3D ld(df.avail_clusters);
                davail*=3D ld(df.bytes_per_sector);
                davail*=3D ld(df.sectors_per_cluster);
                total =3D ld(df.total_clusters);
                total*=3D ld(df.bytes_per_sector);
                total*=3D ld(df.sectors_per_cluster);
            } else {
                printf("ERROR:_dos_getdiskfree() failed, int21h 7303h
failed#2.  everything failed. drive %c:\n", drive-1+'a');//DEBUG
                return false;
            }
        } else {
#if defined(DEBUG_2)
            printf("AX=3D0x%04x,FLAGS=3D0x%04x\n", r.x.ax, r.x.flags);//
DEBUG
#endif
            //success on int 21h 7303h, so extract results.

            //convert ES:DI address from the int21h call into a djgpp
"offset".
            // you can only do this my doing the math ops
individually.
            int adr=3Dr.x.es; //personally I think using a signed int in
the spec of dosmemget was a mistake!
            adr<<=3D4;
            adr +=3D r.x.di;
#if defined(DEBUG_2)
            printf("adr=3D0x%x\n", adr);//DEBUG
#endif
            dosmemget(adr, sizeof(extFAT32FreeSpaceStructure), pds);

            if (pds->struct_size < 0x24
            || pds->struct_size > sizeof(extFAT32FreeSpaceStructure))
{
#if defined(DEBUG_2)
                printf("ERROR:structure size returned=3D0x%04x on drive
%d while CX=3D0x%x\n",pds->struct_size, drive, r.x.cx);//DEBUG
#endif

                if (0=3D=3D_dos_getdiskfree(drive, &df)) { // 0=3Ddefault,
1=3Da, 2=3Db...
#if defined(DEBUG_2)
                    printf("_dos_getdiskfree() SUCCESS, int21h 7303h
failed#3. sizeof struct was %hd,flags=3D0x%04x,AX=3D0x%04x\n",pds-
>struct_size,r.x.flags,r.x.ax);//DEBUG
#endif
                    iDAvail =3Ddf.avail_clusters;         iTotal
=3Ddf.total_clusters;
                    iDAvail*=3Ddf.bytes_per_sector;
iTotal*=3Ddf.bytes_per_sector;
                    iDAvail*=3Ddf.sectors_per_cluster;
iTotal*=3Ddf.sectors_per_cluster;
                    //cout.setf(ios::fixed);
                    //cout.unsetf(ios::scientific);
                    davail =3D ld(df.avail_clusters);
                    davail*=3D ld(df.bytes_per_sector);
                    davail*=3D ld(df.sectors_per_cluster);
                    total =3D ld(df.total_clusters);
                    total*=3D ld(df.bytes_per_sector);
                    total*=3D ld(df.sectors_per_cluster);
                } else {
                    printf("ERROR:_dos_getdiskfree() failed on drive
%d, int21h 7303h failed. everything failed.\n", drive);
                    return false;
                }
            } else {

#if defined(DEBUG_2)
                printf("SUCCESS on int21h 7303h\n");//DEBUG
#endif
                iDAvail =3D pds-
>number_of_sectors_per_cluster_with_adjustment_for_compression;
                iDAvail *=3D pds->number_of_bytes_per_sector;
                iDAvail *=3D pds->number_of_available_clusters;

                iTotal =3D pds-
>number_of_sectors_per_cluster_with_adjustment_for_compression;
                iTotal *=3D pds->number_of_bytes_per_sector;
                iTotal *=3D pds->total_number_of_clusters_on_the_drive;
            }
        }
    }
    free(pds);
//... do something with iiDAvail and iTotal and davail and total.
}





the successful assembly program was using a structure size of 30h and
was passing this size on before he called int 21h.  I am also using a
structure size of 30h, but no joy.

- Raw text -


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