home *** CD-ROM | disk | FTP | other *** search
- /* devinit.c -- Initialize disk device attributes */
- /* Copyright 1991, Steven W. Harrold - All rights reserved */
- /* $Header: DEVINIT.C_V 1.4 91/03/20 08:48:19 SWH Exp $ */
-
- #include <stdlib.h>
- #include <ctype.h>
- #include <stddef.h>
- #include "mfs.h"
- #include "dev.h"
-
- int Dstatus = 0 ; /* Status returned from last dev operation */
-
- PRIVATE struct devdata *devinitf (int drive, int sides) ;
- PRIVATE struct devdata *devinith (int drive) ;
-
-
- /*================================================================*/
- /* This routine determines the geometry of the disk in the specified
- ** physical drive.
- **
- ** For floppy disks, the drives are identified by:
- **
- ** 0x00 ===> the A: drive
- ** 0x01 ===> the B: drive, and so on.
- **
- ** The physical attributes reported are a function both of the
- ** floppy drive AND the disk inserted in it.
- **
- ** For hard disks, the PHYSICAL drives are identified by:
- **
- ** 0x80 ===> physical hard disk 0
- ** 0x81 ===> physical hard disk 1, and so on.
- **
- ** The routine IGNORES the logical partitioning of a hard disk drive,
- ** as it reports the attributes of the physical device. Make sure the
- ** drive identifier is NOT a function of its logical identity. In
- ** particular, C: usually corresponds to physical device 0x80, but
- ** if D: is a second partition on the disk, it will not correspond
- ** to physical 0x81.
- */
-
- struct devdata *devinit (drive, sides)
- int drive ; /* For floppies: 0 is A:, 1 is B:, etc */
- /* Hard drives: 0x80 is PHYSICAL disk 0, 0x81 is 1 */
- int sides ; /* 0 = determine actual value; non-0 = accept value */
- /* Use 1 when 160KB disk has a formatted 2nd side */
- {
- if ((0xff & drive) >= 0x80)
- return devinith (drive) ;
- else
- return devinitf (drive, sides) ;
-
- } /* devinit() */
-
-
- /*================================================================*/
- /* This routine services only floppy disk drives. It determines,
- ** through trial and error, the geometry of the inserted disk.
- ** The actual type of drive is not determined.
- **
- ** The possibilites recognized are:
- **
- ** disk heads tracks sectors
- ** --------- ----- ------ -------
- ** 160 KB 5.25" 1 40 8 rare
- ** 320 KB 5.25" 2 40 8 less rare
- ** 360 KB 5.25" 2 40 9 DSSD
- ** 720 KB 5.25" 2 80 9 popular in Europe?
- ** 1.2 MB 5.25" 2 80 15 DSDD
- ** 720 KB 3.5" 2 80 9 low density
- ** 1.4 MB 3.5" 2 80 18 high density
- */
-
- PRIVATE struct devdata *devinitf (drive, sides)
- int drive ; /* For floppies: 0 is A:, 1 is B:, etc */
- int sides ; /* 0 = determine actual value; non-0 = accept value */
- /* Use 1 when 160KB disk has a formatted 2nd side */
- {
- struct devdata ddata, *dp ;
- int head, track, sector ;
- int done ;
- char buffer[SECTOR_SIZE] ;
-
-
- /* Establish an interim data block
- */
- dp = &ddata ;
- dp->d_drive = drive ;
-
- /* Set the device addresses to minimum legal values. We operate with
- ** these small values because we have no assurance that a disk has been
- ** formatted to its capacity point. If the disk is only partially
- ** formatted, surely the first track, head and sector positions must
- ** be present.
- */
- head = 0 ;
- track = 0 ;
- sector = 1 ;
-
- /* The disk is accessed with various known max values looking for the
- ** fail points. The case of (status==NEW_MEDIA) indicates that the disk
- ** has been re-inserted while this test is underway, and so we have to
- ** start the determination all over again from the start.
- */
- done = 0 ;
- while (!done)
- {
-
- /* Reset the controller so that we have a known hardware state. If the
- ** floppy drive is not installed, the reset will fail.
- */
- Dstatus = BIOSDISK(_DISK_RESET) ;
- if (Dstatus == NEW_MEDIA) continue ;
- if (Dstatus)
- return NULL ;
-
- /* Determine number of sectors accessible on the disk. A NO_SECTOR or a
- ** NO_MARKER status is expected if we reached too far. First sector is
- ** number 1. Note that we use max values for sector, but leave track
- ** and head at their minimum values.
- */
- sector = 18 ; /* 1 of 4 possible values */
- Dstatus = BIOSDISK(_DISK_VERIFY) ;
- if (Dstatus) BIOSDISK(_DISK_RESET) ;
- if (Dstatus == NEW_MEDIA) continue ;
- if ((Dstatus == NO_MARKER) || (Dstatus == NO_SECTOR))
- sector = 15 ; /* 2nd of 4 possibilities */
- else if (Dstatus)
- return NULL ;
-
- if (sector == 15) /* True if previous attempt failed */
- {
- Dstatus = BIOSDISK(_DISK_VERIFY) ;
- if (Dstatus) BIOSDISK(_DISK_RESET) ;
- if (Dstatus == NEW_MEDIA) continue ;
- if ((Dstatus == NO_MARKER) || (Dstatus == NO_SECTOR))
- sector = 9 ; /* 3rd of 4 possibilities */
- else if (Dstatus)
- return NULL ;
- }
-
- if (sector == 9) /* True if previous attempt failed */
- {
- Dstatus = BIOSDISK(_DISK_VERIFY) ;
- if (Dstatus) BIOSDISK(_DISK_RESET) ;
- if (Dstatus == NEW_MEDIA) continue ;
- if ((Dstatus == NO_MARKER) || (Dstatus == NO_SECTOR))
- sector = 8 ; /* try the 4th possibility */
- else if (Dstatus)
- return NULL ;
- }
-
- if (sector == 8) /* True if previous attempt failed */
- {
- Dstatus = BIOSDISK(_DISK_VERIFY) ;
- if (Dstatus) BIOSDISK(_DISK_RESET) ;
- if (Dstatus == NEW_MEDIA) continue ;
- if (Dstatus) /* it's probably unformatted */
- return NULL ;
- }
-
- dp->d_sectors = sector ;
- sector = 1 ; /* resume min value for next tests */
-
- /* Determine number of heads accessible on the disk. Generally, there
- ** should always be two present, but a 160KB disk that is truly
- ** unformatted on the second side will show only 1. Heads start with
- ** number 0.
- */
- if (sides == 0) /* test heads if no override supplied */
- {
- head = 1 ;
- Dstatus = BIOSDISK(_DISK_VERIFY) ;
- if (Dstatus) BIOSDISK(_DISK_RESET) ;
- if (Dstatus == NEW_MEDIA) continue ;
- if ((Dstatus == NO_MARKER) || (Dstatus == NO_SECTOR))
- head = 0 ;
- else if (Dstatus)
- return NULL ;
- }
- else
- head = sides - 1 ; /* assumes caller said 1 or 2 */
-
- dp->d_heads = head + 1 ;
- head = 0 ; /* resume min value */
-
- /* Determine number of tracks accessible on the disk. A NO_MARKER
- ** status is expected if we attempted to reach too far. We try here
- ** to avoid seeking an excessive distance past a non-existent track
- ** as this causes the "grinding" noise we sometimes hear in a
- ** floppy drive. As the first track is number 0, a 40 track disk
- ** should fail with a track address of 40.
- **
- ** It seems that some floppy disk drives can seek 1 extra cylinder,
- ** so, as an extra precaution, a failpoint of 41 is used rather than
- ** the theoretical 40. This should still avoid "head banging".
- */
- track = 41 ; /* "one" past the 1st max value of 39 */
- Dstatus = BIOSDISK(_DISK_VERIFY) ;
- if (Dstatus) BIOSDISK(_DISK_RESET) ;
- if (Dstatus == NEW_MEDIA) continue ;
- if ((Dstatus == NO_MARKER) || (Dstatus == NO_SECTOR))
- dp->d_tracks = 40 ; /* it is the first possibility */
- else if (Dstatus)
- return NULL ;
- else
- dp->d_tracks = 80 ; /* must be the other possibility */
-
- /* When we get here, it means the disk/drive combo has been determined
- ** without a NEW_MEDIA status getting in the way.
- */
- done = 1 ;
-
- } /* while */
-
- /* We can know nothing about the interleave factor nor the offset of
- ** the partition, as these do not apply to a floppy, only a hard disk.
- ** The geometry data is set to values of 1:1 and 0 respectively.
- */
- dp->d_interleave = 1 ;
- dp->d_partoff = 0 ;
- dp->d_partnum = 0 ;
- dp->d_status = 0 ;
-
- /* Allocate the permanent data block for return to caller.
- */
- dp = malloc (sizeof(ddata)) ;
- if (!dp)
- {
- Dstatus = -1 ;
- return NULL ;
- }
- memcpy (dp, &ddata, sizeof(ddata)) ;
-
- return dp ;
-
- } /* devinitf() */
-
-
- /*================================================================*/
- /* Examines a physical hard drive
- ** **NOT IMPLEMENTED**
- */
-
- PRIVATE struct devdata *devinith (drive)
- int drive ;
- {
- Dstatus = -2 ;
- return NULL ;
-
- } /* devinith() */
-
-
- #ifdef MSC
- /*================================================================*/
- /* The biosdisk() function is standard in the TurboC library.
- ** We supply it here for the Microsoft case.
- */
-
- int biosdisk (cmd, drive, head, track, sector, nsectors, buffer)
- int cmd ;
- int drive ;
- int head ;
- int track ;
- int sector ;
- int nsectors ;
- void *buffer ;
- {
- unsigned status ;
- struct diskinfo_t di ;
-
- di.drive = drive ;
- di.head = head ;
- di.track = track ;
- di.sector = sector ;
- di.nsectors = nsectors ;
- di.buffer = (void far *)buffer ;
-
- status = _bios_disk (cmd, &di) ; /* bios_disk() is in MSC library */
- status >>= 8 ;
-
- return status ;
-
- } /* biosdisk() */
-
- #endif /* MSC */
-
-
- /*---eof---*/
-