Mail Archives: djgpp/2011/03/16/19:30:10
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 -