• C

In 16-bit, how do I check whether Drive A is formatted or not?

In my program, I try to write sth to Drive A, so I need to check the status of A drive, the first is whether Drive A is formatted.  
I think _bios_disk can't work, this one always work no matter the drive A is formatted or not. _dos_open also can't. when I use this one to access A drive, it will give me the Abort, Retry, and Fail, if it's not formatted. I don't want my end user to see this message. besides, I will lose control.

Any idea to detect whether A is formatted or how to disable the Abort, Retry, and Fail, or and a handler?

Thanks
Wenfeng
wenfengAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

lif081199Commented:
Here is a small assembler function. It's from Pascal, but, since all the code is in assembler, using it in C is easy.

function diskready(drive:CHAR):BOOLEAN; assembler;
asm
  cmp  drive,'a'
  jb   @isupcase  { make it UPPER case }
  sub  drive,20H
  @isupcase:
  cmp  drive,'Z'
  jb   @driveok
  mov  drive,'A'  { if drive isn't between 'A' and 'Z', make it A) }
  @driveok:
  mov  ax, seg buf
  mov  es, ax
  mov  bx, offset buf

  mov  ah, 02  { read disk sectors }
  mov  al, 1   { number of sectors to transfer }
  mov  ch, 1   { track number }
  mov  cl, 1   { sector number }
  mov  dh, 1   { head number }

  mov        dl, drive
  sub        dl, 'A'     { subtract ORD of 'A' }

  {mov  dl, drive   { drive number (0=A, 3=C, or 80h=C, 81h=D) }
  int  13h

  mov  bl,true { assume drive is ready }
  and  ah,$80
  jz   @done   { error was something other than disk not ready }
  mov  bl,false{ disk wasn't ready. store result }
  @done:

  mov  ax,$0000  { reset drive }
  INT  13H

  xor  ax,ax   { shut off disk drive quickly }
  mov  es,ax
  mov  ax,440h
  mov  di,ax
  mov  byte ptr es:[di],01h

  mov  al,bl   { retrieve result }
end;  { diskready }

Hope this will help you.
Lionel.


0
lif081199Commented:
Following code works under DOS/Windows'95:

static char buffer[512];

int driveReady (char drive)
{
  int  counter;

  if ( drive > 'B' ) return 0;

  drive -= 'A';

  asm {
    xor ax, ax
    mov dl, drive
    int 13h
  }

  for ( counter = 0; counter < 3; counter++ )
  {
    asm {
      push es
      mov  ax, seg buffer
      mov  es, ax
      mov  bx, offset buffer
      mov  ax, 0201h
      mov  cx, 0001h
      mov  dh, 0
      mov  dl, drive
      int  13h
      jc   short lblError
      pop  es
    }

    return 1;

lblError:

    asm {
      pop es
      xor ax, ax
      mov dl, drive
      int 13h
      jc  short lblFatalError
    }
    continue;

lblFatalError:

    break;
  }

  asm {
    xor ax, ax
    mov dl, drive
    int 13h
  }

  return 0;
}
0
wenfengAuthor Commented:
First thanks for your reply. But you didn't get what I mean. You code tests whether drive A is ready. There is a C rouine _bios_disk can do the same job.

What I need is to test whether Drive A is formatted. Basically, bios calling can't do the job, because whether formatted is DOS oriented.


Thanks
Wenfeng
 
0
Simple Misconfiguration =Network Vulnerability

In this technical webinar, AlgoSec will present several examples of common misconfigurations; including a basic device change, business application connectivity changes, and data center migrations. Learn best practices to protect your business from attack.

lif081199Commented:
Try this :
A common way is to use GetFileAttributes() on the root directory.  
if GetFileAttributes fails, you can check the problem (disk missing, disk not formatted) with looking at GetLastError().


On the other way, read this question:
http://www.experts-exchange.com/jsp/qShow.jsp?ta=delphi&qid=10084221 
0
rmichelsCommented:
Once you have determined there is a disk in the drive, try the following DOS function.  It will give you the media descriptor byte of the drive.

(this is from Ralf Brown's interrupt list document)

INT 21 - DOS 1+ - GET ALLOCATION INFORMATION FOR DEFAULT DRIVE
      AH = 1Bh
Return: AL = sectors per cluster (allocation unit)
      CX = bytes per sector
      DX = total number of clusters
      DS:BX -> media ID byte
Notes:      under DOS 1.x, DS:BX points at an actual copy of the FAT; later
        versions return a pointer to a copy of the FAT's ID byte
      this function may not be properly supported on CD-ROMs and other
        installable file systems (use AX=4402h"CD-ROM" for CD-ROMs
        instead)
BUG:      DOS 7.10 (Win95B/Win98) reportedly returns incorrect values in AL and
        DX for FAT12/FAT16 drives, even though it manages correct results
        for FAT32 drives (DOS windows are not affected, only real-mode
        DOS)
SeeAlso: AH=1Ch,AH=36h


Values for media ID byte:
 FFh      floppy, double-sided, 8 sectors per track (320K)
 FEh      floppy, single-sided, 8 sectors per track (160K)
 FDh      floppy, double-sided, 9 sectors per track (360K)
 FCh      floppy, single-sided, 9 sectors per track (180K)
 FAh      HP 200LX D: ROM disk, 16 sectors per track (995K)
      HP 200LX E: (Stacker host drive ???)
 F9h      floppy, double-sided, 15 sectors per track (1.2M)
      floppy, double-sided, 9 sectors per track (720K,3.5")
 F8h      hard disk
 F0h      other media
      (e.g. floppy, double-sized, 18 sectors per track -- 1.44M,3.5")
0
wenfengAuthor Commented:
My application is 16-bits, running under dos. GetFileAttributes won't work.


rmichels, can you pls summerize your ansewer in C, and explain what this mean. I am assembly illiterate.

Wenfeng
0
mmessuriCommented:
wenfeng:

Give the below code a try, that is if your comipler supports it:

#include <stdio.h>
#include <dos.h>

int main(void)
{
   struct fatinfo diskinfo;
   int flag = 0;

   printf("Please insert disk in drive A\n");
   getchar();

   getfat(1, &diskinfo);
/* get drive information */

   printf("\nDrive A: is ");
   printf("%02x\n", (unsigned char)diskinfo.fi_fatid);
   switch((unsigned char) diskinfo.fi_fatid)
   {
/*
  -- Possible return types:
    FFh      floppy, double-sided, 8 sectors per track (320K)
    FEh      floppy, single-sided, 8 sectors per track (160K)
    FDh      floppy, double-sided, 9 sectors per track (360K)
    FCh      floppy, single-sided, 9 sectors per track (180K)
    FAh      HP 200LX D: ROM disk, 16 sectors per track (995K)
          HP 200LX E: (Stacker host drive ???)
     F9h      floppy, double-sided, 15 sectors per track (1.2M)
          floppy, double-sided, 9 sectors per track (720K,3.5")
     F8h      hard disk
     F0h      other media
          (e.g. floppy, double-sized, 18 sectors per track -- 1.44M,3.5")
*/
      case 0xFD:
        printf("360K low density\n");
        break;

      case 0xF9:
        printf("1.2 Meg high density\n");
        break;

      default:

        printf("unformatted\n");
        flag = 1;
   }

   if (!flag)
   {
      printf("  sectors per cluster %5d\n", diskinfo.fi_sclus);
      printf("   number of clusters %5d\n", diskinfo.fi_nclus);
      printf("     bytes per sector %5d\n", diskinfo.fi_bysec);
   }

   return 0;
}


-- mmessuri --
0
rmichelsCommented:
mmessuri

You kind of jumped into my answer.  I proposed a similar solution.  The only reason it was rejected was it being asm code instead of C code.  The DOS function I outlined would be the basis of the getfat function.

If it works, for wenfeng, then it helps him out.  If not, then wenfeng can try the my ammended answer.

I have noticed you have not answered many questions, so maybe you don't have alot of experience here on EE?  Generally the protocol would have been for me to supply the additional requested information, since wenfeng asked for clarification.

Here is the asm function in C.  I don't have a 16 bit compiler, so I can't test it out.  It will return the following values:

FFh floppy, double-sided, 8 sectors per track (320K)
                        FEh floppy, single-sided, 8 sectors per track (160K)
                        FDh floppy, double-sided, 9 sectors per track (360K)
                        FCh floppy, single-sided, 9 sectors per track (180K)
                        FAh HP 200LX D: ROM disk, 16 sectors per track (995K)
                       HP 200LX E: (Stacker host drive ???)
                        F9h floppy, double-sided, 15 sectors per track (1.2M)
                       floppy, double-sided, 9 sectors per track (720K,3.5")
                        F8h hard disk
                        F0h other media

//
// drive - 1 = a, 2 = b...

unsigned char GetMediaDescriptor(unsigned char drive)
{
   unsigned char media;

//
// inline asm instruction (asm) will vary by
// compiler
//
asm{


   mov ah, 1ch
   mov dl, drive
   int 21h

   mov media, byte ptr [bx]
}

   return media;

}


This function returns a byte that describes the media in the desired drive.
0
wenfengAuthor Commented:
Hello,

I tried all your suggestion. still can't get it.

char media;
       union _REGS inregs, outregs;
       
            _chdrive(1);
            inregs.h.ah = 0x1b;              
            _intdos( &inregs, &outregs );
       if (outregs.x.bx != 0)
       {      
                   media = *(char*) outregs.x.bx;
                   printf("%x\n", media);
       }


when there is a standard floppy disk, 1.4 mega, .... it seems bx is 0.

I tried the 0x1c also, it doesn't work. It does check floppy disk. the result always strange.

I am using Vc++ 1.5, it doesn't have the gatfat, or am I somewhere wrong?

also, mov media, byte ptr [bx] doesn't compile.


Any suggestions?

Wenfeng.
0
KangaRooCommented:
Although  not ANSI C there is an common function that can be used for this:
    int access (const char *filename, int how)

It returns -1 (non zero) if access is denied. The how argument may vary from system to system, on gcc use F_OK, Borland the value 0 should work. Check out your compilers manual.

// tested with gcc 2.8 (Mingw32)
#include <stdio.h>
#include <errno.h>
#include <unistd.h>

int main()
{
   access("A:\\", F_OK);
   printf("errno: %d\n", errno);
   perror("Errno:");

}
0
sergelebelCommented:
Try this code!

Floppy_rdy ensures there is a disk in the drive..and the getfat ensures it is usable..
(formatted)..

I only commented this answer since earlier answers are correct except I did not use the library routines...

Hope it works for you!


#include <stdio.h>
#include <ctype.h>
#include <dos.h>
#include <alloc.h>
#include <stdlib.h>

#define SECTOR_SIZE 512     /* default sector size */
#define RETRY       1       /* # of retries */

int     SUCCESS, ERROR;

int floppy_rdy (drv)
char drv;       /* 'A' or 'B' */
{
    int cnt;
    union REGS inregs, outregs;
    struct SREGS segregs;
    unsigned char far * buffer;

    buffer = malloc(SECTOR_SIZE);           /* allocate temp sector buffer */
    cnt = 0;
    while (1) {
        inregs.h.ah = 0x04;                 /* function # */
        inregs.h.al = 1;                    /* # of sectors */
        inregs.h.ch = 0;                    /* 1st cylinder */
        inregs.h.cl = 1;                    /* 1st sector */
        inregs.h.dh = 0;                    /* 1st side */
        inregs.h.dl = toupper(drv) - 'A';   /* drive ('A' = 0) */
        segregs.es = FP_SEG(buffer);        /* ES:BX pt to buffer (for old BIOS's) */
        inregs.x.bx = FP_OFF(buffer);
        int86x(0x13, &inregs, &outregs, &segregs);      /* call Int 13H */

        if (!outregs.h.ah) break;           /* status ok -- return */
        if (++cnt > RETRY) break;           /* already retried */

        /* otherwise retry -- first issue reset */
        inregs.h.ah = 0x00;                 /* function # */
        inregs.h.dl = toupper(drv) - 'A';   /* drive ('A' = 0) */
        int86(0x13, &inregs, &outregs);     /* call Int 13H */
    }

    free(buffer);
    return(!outregs.h.ah);                  /* return TRUE if drive ready */
}

/*
    getdrv()

    Just as getcwd() returns the default directory, getdrv() returns
    the current drive.

    Arguments: None.

    Returns:   Current drive (0 = A:, 1 = B:, etc.)

    Side effects: none
*/

int getdrv (void)
{
      union REGS regs;

      regs.h.ah = 0x19;
      intdos(&regs, &regs);
      return (regs.h.al);
}

/*
 chdrv()

 Like chdir(), except changes drives rather than directories.

    Arguments: 1 - target drive (0 = A:, 1 = B:, etc.)

    Returns: SUCCESS or ERROR

    Side effects: none
*/

int chdrv (int drive)
{
      union REGS regs;

      regs.h.ah = 0x0e;
      regs.h.dl = (char)drive;
      intdos(&regs, &regs);
      if (drive != getdrv())
            return ERROR;
      else  return SUCCESS;
}


/*
    getfatt ()

    Gets the File Allocation Table info of current drive

Returns: 255 if Diskette not usable (not formatted)
*/

int getfatt (void)
{
      union REGS regs;

      regs.h.ah = 0x1B;
      intdos(&regs, &regs);
      return (regs.h.al);
}


main() {
int Default = 0;
int Status = 0;

    if (floppy_rdy ('A')) {
        printf("Drive is Ok\n");
        Default = getdrv();
        Status  = (SUCCESS == chdrv(0));
        if (Status) {
            Status = getfatt ();
            if (Status == 255)
                printf("Floppy Not Ready\n");
            else
                printf("Floppy is Ok\n");
        }
        chdrv (Default);
    }
    else
        printf("Drive Not Ready\n");

}
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
wenfengAuthor Commented:
Great,
I don't know the I should check whether al == 255. I kept trying the bx. that's why I reject the previous answer.

I would like to give the credits. but there is no proposal answer.

Pls answer again, so that I can give the points.

Thanks
Wenfeng.
0
YensidModCommented:
Points to sergelebel.

YensidMod
EE Moderator
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C

From novice to tech pro — start learning today.