home *** CD-ROM | disk | FTP | other *** search
- /**********************************************************************
- *
- * NAME: hdio.c
- *
- * DESCRIPTION: hard disk i/o (int 13h)
- *
- * M O D I F I C A T I O N H I S T O R Y
- *
- * when who what
- * -------------------------------------------------------------------
- * 04/24/90 J. Alan Eldridge created from badclu.c
- *
- *********************************************************************/
-
- #include <string.h>
- #include <stdlib.h>
- #include <bios.h>
-
- #include "hdio.h"
-
- /**********************************************************************
- * some static vars used to keep status info
- *********************************************************************/
-
- static int Drive = 0,
- Partition = 0,
- fatdirty = 0;
-
- /**********************************************************************
- * the File Allocation Table storage pointer
- *********************************************************************/
-
- static UINT *fat = NULL;
-
- /**********************************************************************
- * the biosdisk() function gives us drive info like this
- *********************************************************************/
-
- typedef struct {
- UCHAR max_secs;
- UCHAR max_cyls;
- UCHAR num_drvs;
- UCHAR max_hds;
- } DISK_PARMS;
-
- /**********************************************************************
- * static work areas
- *********************************************************************/
-
- static DISK_PARMS diskparms;
- static PART_TBL part_tbl;
- static BOOT_SEC boot_sector;
- static PARTITION curr_part;
- static DISK_INFO diskinfo;
- static DOS_PARTITION curr_DOS;
-
- /**********************************************************************
- * select disk & partition to use
- *********************************************************************/
-
- void
- hdSelDiskPart(
- int d,
- int p)
- {
- Drive = d;
- Partition = p;
- }
-
- /**********************************************************************
- * internal use:
- * DOS stores the 2 high order bits of the cylinder number
- * in the 2 top bits of the sector number. this is inconvenient.
- *********************************************************************/
-
- static void
- getCylSec(
- UCHAR cyl,
- UCHAR sec,
- UINT *cylw,
- UINT *secw)
- {
- *cylw = cyl | ((sec << 2) & 0x300);
- *secw = sec & 0x3f;
- }
-
- /**********************************************************************
- * if we have a DOS partition, calculate the extra info
- * using the boot sector and fill in a DOS partition structure
- *********************************************************************/
-
- static void
- parttoDOS(
- PARTITION *part,
- BOOT_SEC *boot,
- DOS_PARTITION *dos)
- {
- dos->part = *part;
- dos->dir0 = boot->num_fats * boot->sec_per_fat + 1;
- dos->dsec = (boot->num_root_ent * 32) / boot->bytes_per_sec;
- dos->dat0 = dos->dir0 + dos->dsec;
- dos->nclu = (boot->num_sec - dos->dat0) / boot->sec_per_clust;
- }
-
- /**********************************************************************
- * convert a partition table entry in disk form to a partition
- * structure that we can use more readily
- *********************************************************************/
-
- static void
- PEtoPart(
- PART_ENT *pent,
- PARTITION *part)
- {
- part->boot = pent->boot;
- part->type = pent->type;
- part->rel_sec = pent->rel_sec;
- part->num_sec = pent->num_sec;
- part->beg.hd = pent->beg.hd;
- part->end.hd = pent->end.hd;
- getCylSec(pent->beg.cyl,pent->beg.sec,
- &part->beg.cyl, &part->beg.sec);
- getCylSec(pent->end.cyl,pent->end.sec,
- &part->end.cyl, &part->end.sec);
- }
-
- /**********************************************************************
- * get the indicated partition # and set up the static partition
- * structure; if the # is -1, use the value of Partition
- *********************************************************************/
-
- int
- hdGetPart(int pn)
- {
- int n, p;
-
- if (pn == -1)
- pn = Partition;
- for (p = n = 0; n < 4; n++) {
- UCHAR ptype = part_tbl.part_ents[n].type;
-
- if (ptype == PRI_DOS_12 || ptype == PRI_DOS_16 || ptype == EXT_DOS)
- if (p++ == pn) {
- PEtoPart(part_tbl.part_ents + n, &curr_part);
- Partition = p-1;
- return 0;
- }
- }
- return -1;
- }
-
- /**********************************************************************
- * set up the static structure for the primary DOS partition.
- * this sets the static var Partition to the index in the table.
- *********************************************************************/
-
- int
- hdGetPriDOS(void)
- {
- int n;
-
- for ( n = 0; n < 4; n++) {
- UCHAR ptype = part_tbl.part_ents[n].type;
-
- if (ptype == PRI_DOS_12 || ptype == PRI_DOS_16) {
- PEtoPart(part_tbl.part_ents + n, &curr_part);
- Partition = n;
- return 0;
- }
- }
- return -1;
- }
-
- /**********************************************************************
- * set up the static structure for the extended DOS partition.
- * this sets the static var Partition to the index in the table.
- *********************************************************************/
-
- int
- hdGetExtDOS(void)
- {
- int n;
-
- for ( n = 0; n < 4; n++) {
- if (part_tbl.part_ents[n].type == EXT_DOS) {
- PEtoPart(part_tbl.part_ents + n, &curr_part);
- Partition = n;
- return 0;
- }
- }
- return -1;
- }
-
- /**********************************************************************
- * return a pointer to the current partition, copying the
- * structure to a user area if pointer is not NULL
- *********************************************************************/
-
- PARTITION *
- hdCurrPart(PARTITION *p)
- {
- if (p) {
- *p = curr_part;
- return p;
- } else
- return &curr_part;
- }
-
- /**********************************************************************
- * convert a cluster # for the current partition to an absolute (0 based)
- * sector # (from the start of the partition)
- *********************************************************************/
-
- UINT
- hdClutoSec(UINT clu)
- {
- if (clu >= curr_DOS.nclu)
- return 0;
- return clu * boot_sector.sec_per_clust + curr_DOS.dat0;
- }
-
- /**********************************************************************
- * if the current partition structure is a DOS partiton, fill in
- * the static DOS partition structure
- *********************************************************************/
-
- int
- hdGetDOSPart(void)
- {
- if (curr_part.type == PRI_DOS_12 || curr_part.type == PRI_DOS_16) {
- parttoDOS(&curr_part, &boot_sector, &curr_DOS);
- return 0;
- } else
- return -1;
- }
-
- /**********************************************************************
- * return a pointer to the current DOS partition, copying the
- * structure to a user area if pointer is not NULL
- *********************************************************************/
-
- DOS_PARTITION *
- hdCurrDOS(DOS_PARTITION *dp)
- {
- if (dp) {
- *dp = curr_DOS;
- return dp;
- } else
- return &curr_DOS;
- }
-
- /**********************************************************************
- * convert an absolute sector # to cyl, hd, sec form
- *********************************************************************/
-
- static void
- calcCHS(
- UINT sector,
- UINT *cyl,
- UINT *sec,
- UINT *head)
- {
- UINT hcnt,
- scnt;
-
- ULONG lsec;
-
- hcnt = diskinfo.hds;
- scnt = diskinfo.sec;
-
- lsec = (ULONG)sector + curr_part.rel_sec;
-
- *cyl = lsec / (hcnt*scnt);
- *head = (lsec / scnt) % hcnt;
- *sec = 1 + (lsec % scnt);
- }
-
- /**********************************************************************
- * read/write/verify an absolute sector
- *********************************************************************/
-
- int
- hdRWVSector(
- UINT rwv,
- UINT sector,
- UINT cnt,
- void *buffer)
- {
- UINT hd,
- cyl,
- sec;
-
- calcCHS(sector, &cyl, &sec, &hd);
-
- return biosdisk(rwv, Drive|0x80, hd, cyl, sec, cnt, buffer) & 0xff;
- }
-
- /**********************************************************************
- * fill in static diskinfo structure with BIOS call
- *********************************************************************/
-
- int
- hdGetDiskInfo(void)
- {
- int ret;
-
- ret = biosdisk(8,Drive|0x80,0,0,0,0,&diskparms) & 0xff;
- if (ret == 0) {
- diskinfo.drv = diskparms.num_drvs;
- diskinfo.hds = diskparms.max_hds + 1;
- getCylSec(diskparms.max_cyls, diskparms.max_secs,
- &diskinfo.cyl, &diskinfo.sec);
- }
- return ret;
- }
-
- /**********************************************************************
- * return a pointer to the current disk info, copying the
- * structure to a user area if pointer is not NULL
- *********************************************************************/
-
- DISK_INFO *
- hdDiskInfo(DISK_INFO *di)
- {
- if (di) {
- *di = diskinfo;
- return di;
- } else
- return &diskinfo;
- }
-
- /**********************************************************************
- * reset disk system with BIOS call
- *********************************************************************/
-
- int
- hdDiskReset(void)
- {
- return biosdisk(0,Drive|0x80,0,0,0,0,NULL) & 0xff;
- }
-
- /**********************************************************************
- * read partition table into static work area with BIOS call
- *********************************************************************/
-
- int
- hdGetPartTbl(void)
- {
- return biosdisk(2,Drive|0x80,0,0,1,1,&part_tbl) & 0xff;
- }
-
- /**********************************************************************
- * return a pointer to the current partition table, copying the
- * structure to a user area if pointer is not NULL
- *********************************************************************/
-
- PART_TBL *
- hdPartTbl(PART_TBL *pt)
- {
- if (pt) {
- *pt = part_tbl;
- return pt;
- } else
- return &part_tbl;
- }
-
- /**********************************************************************
- * get boot sector for current partition into static boot sector area
- *********************************************************************/
-
- int
- hdGetBootSec(void)
- {
- return hdRWSector(SEC_READ,0,1,&boot_sector) & 0xff;
- }
-
- /**********************************************************************
- * get boot sector for current partition:
- * if extended partition, get boot sector for first DOS partition
- * in the extended partition
- * NOTE: this only works one level deep; you CAN'T follow extended
- * partitions down the disk with this call. it's only good when called
- * on a partition in the real physical partition table!
- *********************************************************************/
-
- int
- hdGetXBootSec(void)
- {
- int ret;
-
- ret = hdGetBootSec();
- if (ret != 0)
- return ret;
- if (curr_part.type == EXT_DOS) {
- ULONG rel;
-
- rel = curr_part.rel_sec;
- memcpy(&part_tbl, &boot_sector, 512);
- ret = hdGetPriDOS();
- if (ret != 0)
- return ret;
- curr_part.rel_sec += rel;
- hdGetBootSec();
- }
- hdGetDOSPart();
- return 0;
- }
-
- /**********************************************************************
- * return a pointer to the current boot sector, copying the
- * structure to a user area if pointer is not NULL
- *********************************************************************/
-
- BOOT_SEC *
- hdBootSec(BOOT_SEC *bs)
- {
- if (bs) {
- *bs = boot_sector;
- return bs;
- } else
- return &boot_sector;
- }
-
- /**********************************************************************
- * allocate a static area to hold a copy of the FAT
- *********************************************************************/
-
- int
- hdAllocFAT(void)
- {
- if (fat)
- free(fat);
- fat = calloc(boot_sector.sec_per_fat + 1, boot_sector.bytes_per_sec);
- return -(fat == NULL);
- }
-
- /**********************************************************************
- * free the static FAT storage area
- *********************************************************************/
-
- void
- hdFreeFAT(void)
- {
- if (fat) {
- free(fat);
- fat = NULL;
- }
- }
-
- /**********************************************************************
- * read the FAT for the current parition into the static storage area
- *********************************************************************/
-
- int
- hdGetFAT(void)
- {
- fatdirty = 0;
- return hdRWSector(SEC_READ,1,boot_sector.sec_per_fat,fat);
- }
-
- /**********************************************************************
- * write the disk copy or copies of the FAT from the work area
- *********************************************************************/
-
- int
- hdPutFAT(void)
- {
- int ret = 0;
-
- if (fatdirty) {
- int start,
- nfats;
-
- for (start = 1, nfats = 0; nfats < boot_sector.num_fats; nfats++,
- start += boot_sector.sec_per_fat) {
- int err;
-
- err = hdRWSector(SEC_WRITE,start,boot_sector.sec_per_fat,fat);
- if (err)
- ret = err;
- }
- fatdirty = 0;
- }
- return ret;
- }
-
- /**********************************************************************
- * given a cluster # (0 based) get the FAT entry
- *********************************************************************/
-
- UINT
- hdGetFATEnt(UINT n)
- {
- UINT fatent;
-
- n += 2;
-
- if (curr_part.type == PRI_DOS_12) {
- UINT byteoffs;
-
- byteoffs = n * 3;
- byteoffs /= 2;
-
- fatent = *(UINT *)&(((UCHAR *)fat)[byteoffs]);
- if (n & 1)
- fatent >>= 4;
- else
- fatent &= 0xFFF;
-
- if (fatent >= 0xFF7)
- fatent |= 0xF000;
- } else
- fatent = fat[n];
-
- return fatent;
- }
-
- /**********************************************************************
- * given a cluster # (0 based), set the FAT entry
- *********************************************************************/
-
- void
- hdPutFATEnt(
- UINT n,
- UINT v)
- {
- n += 2;
-
- if (curr_part.type == PRI_DOS_12) {
- UINT fatent,
- byteoffs,
- mask;
-
- fatdirty = 1;
-
- byteoffs = n * 3;
- byteoffs /= 2;
-
- fatent = *(UINT *)&(((UCHAR *)fat)[byteoffs]);
- v &= 0xFFF;
- if (n & 1) {
- v <<= 4;
- mask = 0x000F;
- } else {
- mask = 0xF000;
- }
-
- fatent &= mask;
- fatent |= v;
- *(UINT *)&(((UCHAR *)fat)[byteoffs]) = fatent;
- } else
- fat[n] = v;
- }
-
- /**********************************************************************
- * given a cluster # (0 based) mark it as bad
- *********************************************************************/
-
- void
- hdMarkBadClu(UINT n)
- {
- hdPutFATEnt(n,CLUST_BAD);
- }
-
- /**********************************************************************
- * return the size in bytes of a sector and cluster
- *********************************************************************/
-
- void
- hdSecCluSize(UINT *sec, UINT *clu)
- {
- *clu = boot_sector.sec_per_clust * (*sec = boot_sector.bytes_per_sec);
- }
-
-
-