home *** CD-ROM | disk | FTP | other *** search
- /* sect.c */
-
- /*
- * Aug-23-88 jye. Change and add codes so that can be used for MS-DOS
- * Dec-20-89 jye. Free a bug that HDX gives a error message when CD-ROM
- * is busy.
- */
-
- #include "obdefs.h"
- #include "osbind.h"
- #include "mydefs.h"
- #include "part.h"
- #include "hdx.h"
- #include "addr.h"
- #include "error.h"
-
- #define ZBUFSIZ 0x4000 /* about 16k == 32 sectors */
- #define ZCOUNT (ZBUFSIZ/0x200) /* ZCOUNT = 32 */
- #define MAXUNITS 16 /* max number of logical units */
-
- #define PUNINFO struct _punifno
- PUNINFO {
- WORD puns; /* number of physical units */
- BYTE pun[MAXUNITS];
- LONG partition_start[MAXUNITS]; /* offset to partition on */
- /* physical unit */
- };
- extern long ostack; /* old stack pointer */
- extern UWORD errcode(); /* function to return error code */
- extern int yesscan; /* the flag for the func. IBMGPART use */
- extern long sptrk; /* the sector per track */
- extern int npart; /* the number of partitions */
- extern int ext; /* the index of extended partition */
- extern int extend; /* the index of end extended partition */
- extern int showmany; /* the flag for show the too many device alert box */
- extern char ttscsi; /* the flag for SCSI if set */
- extern int t_scsi(); /* the assembly codes for check SCSI drive */
- extern int needscan; /* TRUE: if it is the first time to scan the units */
-
-
- /*
- * Logical-to-dev+partition mapping table.
- */
- int nlogdevs; /* # logical devices */
- LOGMAP logmap[EXTRALOGD]; /* logical dev map */
- int livedevs[MAXPHYSDEVS]; /* live devs flags; 1: device is alive */
- int typedev = 0x0000; /* if set, driver is a removable driver */
- int typedrv = 0x0000; /* if set, driver is a SCSI driver */
-
-
- /*
- * Rebuild logical-to-physical mapping
- * by reading and interpreting the root
- * blocks for all physical devs.
- *
- */
-
- rescan(flag, znm)
-
- int flag; /* 0: don't report medium change error; */
- /* non-0: report medium change error; */
- int znm; /* 1: do zero & markbad; 0: do partition & format */
-
- {
- int dev, scan=0;
- char buf[512];
- char sendata[16];
- int partno, ret, inqret, i;
- PART *partinfo;
- char mask = 0x80; /* 7th bit is set on */
- int setmask;
- int maxloop;
-
- ostack = Super(NULL); /* set supervice mode */
- t_scsi(); /* set the ttscsi flag if SCSI exists */
- delay();
- Super(ostack);
- /* set the scent message box */
- if ((needscan) && (ttscsi))
- dsplymsg(scanmsg);
-
- /* disable all logical and physical devs */
- for (dev = 0; dev < EXTRALOGD; ++dev)
- logmap[dev].lm_physdev = -1;
-
- for (dev = 0; dev < MAXPHYSDEVS; ++dev)
- livedevs[dev] = 0;
-
- /*
- * Scan all physical devs
- * and pick up partition structures.
- */
- nlogdevs = 0;
- showmany = 0;
- if (ttscsi) {
- maxloop = 16;
- dev = 8;
- } else {
- maxloop = 8;
- dev = 0;
- }
- rerescan:
- for (; dev < maxloop; ++dev)
- {
- /* initialize the buffer */
- for (i = 0; i < 16; i++) {
- sendata[i] = 0;
- }
-
- /* check see the drive is a what kind of drive */
- ostack = Super(NULL);
- delay();
- inqret = inquiry(dev, (WORD)16, sendata);
- delay();
- Super(ostack);
- setmask = 0x0001;
- if (inqret & 0x08) { /* the device is busy */
- continue;
- }
- /* ret not equal OK, it may be a regular hard drive */
- if (inqret == OK) { /* it is not a regular hard drive */
- if (sendata[0]) { /* it is not a hard drive */
- continue;
- }
- /* it is a SCSI drive */
- /* set the relative bit, 1 is a SCSI, other is not */
- typedrv |= setmask << dev;
- }
- if ((ret = getroot(dev, buf, (SECTOR)0)) < 0) {
- if (znm) rangelog(dev);
- continue;
- } else { /* ret >= 0 */
- if (ret > 0) {
- if (flag) { /* if non-0, report error if medium changed */
- if (tsterr(ret) == OK)
- return ERROR;
- }
- if ((ret = getroot(dev, buf, (SECTOR)0))) { /* try again */
- if (ret > 0 && flag && tsterr(ret) == OK) {
- return ERROR;
- } else if ((ret > 0) && (!flag)) {
- if ((inqret == OK) && (sendata[1] & mask)) {
- /* it is a removable drive */
- /* but forget insert the cartridge */
- err(instdrv);
- return ERROR;
- }
- }
- if (znm) {
- rangelog(dev);
- }
- continue;
- }
- }
- if (inqret == OK) { /* it is a SCSI drive */
- if (sendata[1] & mask) { /* it is a removable drive */
- /* set the relative bit, 1 is a removable, other is not */
- typedev |= setmask << dev;
- }
- }
- livedevs[dev] = 1;
- yesscan = 1;
- if (stgpart(dev, buf, (PART *)&partinfo) == ERROR) {
- return ERROR;
- }
- if (ext != NO_EXT) {
- sortpart(partinfo,SCAN_BS);
- }
- for (partno = 0; partno < npart; ++partno) {
- if ((partinfo[partno].p_flg & P_EXISTS) &&
- (partinfo[partno].p_siz != (SECTOR)0) &&
- (((partinfo[partno].p_id[0] == 'G') &&
- (partinfo[partno].p_id[1] == 'E') &&
- (partinfo[partno].p_id[2] == 'M')) ||
- ((partinfo[partno].p_id[0] == 'B') &&
- (partinfo[partno].p_id[1] == 'G') &&
- (partinfo[partno].p_id[2] == 'M'))))
- {
- if (nlogdevs > EXTRALOGD) {
- continue;
- }
- logmap[nlogdevs].lm_physdev = dev;
- logmap[nlogdevs].lm_partno = partno;
- logmap[nlogdevs].lm_start = partinfo[partno].p_st;
- logmap[nlogdevs].lm_siz = partinfo[partno].p_siz;
- ++nlogdevs;
- if (nlogdevs == MAXLOGDEVS) {
- showmany = 1;
- }
- }
- }
- }
- inipart(partinfo, npart);
- if (partinfo > 0) Mfree(partinfo);
- }
- if ((ttscsi)&&(maxloop>8)) {
- maxloop = 8;
- dev = 0;
- goto rerescan;
- }
- return OK;
- }
-
- /* rerange the partition informations. */
-
- sortpart(pinfo, type)
- PART *pinfo;
- int type; /* USER_ED = 1: for user interface use */
- /* SCAN_BS = 0: for rescan() and laybs() use */
- {
- int i, j, k;
- PART rpart[2];
-
- if (ext == NO_EXT) return OK; /* don't need sort */
- for (i = 0; i < 2; i++) { /* initialize the temple space */
- rpart[i].p_flg = 0L;
- rpart[i].p_st = 0L;
- rpart[i].p_siz = 0L;
- for (k = 0; k < 3; k++)
- rpart[i].p_id[k] = '0';
- }
- /* save the partitions that after the extened partitions */
- for (i = ext+1, j=0; i < 4; i++, j++) {
- if (pinfo[i].p_flg & P_EXISTS) {
- rpart[j].p_flg = P_EXISTS;
- rpart[j].p_st = pinfo[i].p_st;
- rpart[j].p_siz = pinfo[i].p_siz;
- for (k = 0; k < 3; k++)
- rpart[j].p_id[k] = pinfo[i].p_id[k];
- }
- }
- /* move the extened partition to the front */
- for (i=4, j = ext; i < npart; i++, j++) {
- if (pinfo[i].p_flg & P_EXISTS) {
- pinfo[j].p_flg = P_EXISTS;
- pinfo[j].p_st = (type)?(pinfo[i].p_st):(pinfo[i].p_st + ROOTSECT);
- pinfo[j].p_siz = (type)?(pinfo[i].p_siz):(pinfo[i].p_siz-ROOTSECT);
- for (k = 0; k < 3; k++)
- pinfo[j].p_id[k] = pinfo[i].p_id[k];
- } else { j--;} /* stay with that space */
- }
- /* copy the not extended partitions back after the extended partitions */
- for (i=0; i < 2; i++, j++) {
- if (rpart[i].p_flg & P_EXISTS) {
- pinfo[j].p_flg = P_EXISTS;
- pinfo[j].p_st = rpart[i].p_st;
- pinfo[j].p_siz = rpart[i].p_siz;
- for (k = 0; k < 3; k++)
- pinfo[j].p_id[k] = rpart[i].p_id[k];
- } else {j--;}
- }
- for (i = j; i < npart; i++) { /* set the rest to 0 */
- pinfo[i].p_flg = 0L;
- pinfo[i].p_st = 0L;
- pinfo[i].p_siz = 0L;
- for (k = 0; k < 3; k++)
- pinfo[i].p_id[k] = '0';
- }
- }
-
-
- /*
- * check to find out the exist of device
- */
-
- rangelog(dev)
-
- int dev;
-
- {
- PUNINFO *divinfo;
- int devnum;
-
- ostack = Super(NULL);
- divinfo = ((PUNINFO *) *((long *)(0x516)));
- for (devnum = 0; devnum < MAXUNITS; ++devnum) {
- if ((int)(divinfo->pun[devnum] & 0x07) == dev) {
- delay();
- nlogdevs++;
- }
- }
- Super(ostack);
- }
-
- /*
- * From a PHYSICAL device unit (0->7)
- * and a partition number (0->3), figure
- * out the LOGICAL disk number ('C'->'P').
- *
- * return the LOGICAL disk number or
- * ERROR if the PHYSICAL device doesn't exist.
- *
- */
- phys2log(pdev, pno)
- int pdev; /* physical device unit */
- int pno; /* partition number (0 -> 3) */
- {
- int logdev; /* index to step through partitions of a phys unit */
-
- for (logdev = 0; logdev < EXTRALOGD; logdev++) {
- if (logmap[logdev].lm_physdev == pdev &&
- logmap[logdev].lm_partno == pno)
- return ('C'+logdev);
- }
- return ERROR;
- }
-
-
- /*
- * Map block on logical device to
- * block on physical device;
- * return ERROR if the logical device
- * doesn't exist.
- */
- log2phys(adev, ablk)
- int *adev;
- SECTOR *ablk;
- {
- int dev;
- char xbuf[256];
-
- dev = *adev;
- if (dev >= 0 && dev <= 15)
- return OK;
-
- dev = toupper(dev);
- if (dev >= 'C' && dev <=
- ('C'+EXTRALOGD)) /* from C to 't' are 50 logic device */
- {
- dev -= 'C';
- *adev = logmap[dev].lm_physdev;
- *ablk = logmap[dev].lm_start + *ablk;
- return OK;
- }
-
- return ERROR;
- }
-
-
-
- /*
- * Return physical starting block# of a partition
- *
- */
- SECTOR
- logstart(ldev)
- int ldev; /* logical device */
- {
- ldev = toupper(ldev);
- if (ldev >= 'C' && ldev <=
- ('C'+EXTRALOGD)){/*from C to 't' are 50 logic device */
- ldev -= 'C';
- return (logmap[ldev].lm_start);
- }
- return ERROR;
- }
-
-
-
- /*
- * Return physical starting block# of a partition's data block.
- *
- */
- SECTOR
- logend(ldev)
- int ldev; /* logical device */
- {
- ldev = toupper(ldev);
- if (ldev >= 'C' && ldev <=
- ('C'+EXTRALOGD)){/*from C to 't' are 50 logic device */
- ldev -= 'C';
- return (logmap[ldev].lm_start+logmap[ldev].lm_siz-1);
- }
- return ERROR;
- }
-
-
- #define MFM 17 /* sectors per track for MFM */
- #define RLL 26 /* sectors per track for RLL */
-
-
- /*
- * Check if dev's root block is intact.
- * Return number of sectors per track on disk.
- *
- */
- chkroot(dev, bs)
- int dev;
- char *bs;
- {
- extern long get3bytes();
- SETMODE *mb;
- int i, ret, set, scsidrv, mask=0x0001;
- int cyl, head;
- SECTOR size, msiz; /* size of media */
- char buf[512], sendata[32];
- long dmaptr, tmpptr;
- char *dmahigh=0xffff8609,
- *dmamid=0xffff860b,
- *dmalow=0xffff860d;
-
- size = ((RSECT *)(bs + 0x200 - sizeof(RSECT)))->hd_siz;
-
- ostack = Super(NULL);
-
- /* Get format parameters/ disk size from media */
- set = typedev & (mask << dev);
- scsidrv = typedrv & (mask << dev);
- if ((set) || (scsidrv)) {
- ret = mdsense(dev, 4, 0, 16, sendata);
- } else {
- ret = mdsense(dev, 0, 0, 22, sendata);
- }
- delay();
- Super(ostack);
-
- if (ret != 0) {
- ret = errcode(dev);
- if (tsterr(ret) != OK)
- return ERROR;
- return (-3); /* don't have to show the alert box */
- }
-
- /* check what kind of sense data it returned */
- /* If full SCSI, will return number of blocks */
- /* on disk at byte 5, 6 and 7. If Adaptec, */
- /* will return 0 for number of blocks on disk */
- /* on SCSI. */
-
- if (!(msiz = get3bytes(sendata+5))) { /* no disk size returned? */
- /* Yup, ie., it's adaptec's. Interpret as SETMODE structure */
- mb = (SETMODE *)sendata;
- /* get number of cylinders */
- cyl = mb->smd_cc[0];
- cyl <<= 8;
- cyl |= mb->smd_cc[1];
-
- /* get number of heads */
- head = mb->smd_dhc;
-
- msiz = (SECTOR)head * (SECTOR)cyl * MFM;
-
- for (i = 0; i < 20; i++) {
- if ((ret = rdsects(dev, 1, buf, msiz+i)) == OK) {
-
- /* find out whether data has been transferred, by
- checking if dma pointer has been moved. */
-
- ostack = Super(NULL); /* get into Supervisor mode */
-
- dmaptr = *dmahigh;
- dmaptr &= 0x0000003f;
- dmaptr <<= 16;
- tmpptr = *dmamid;
- tmpptr &= 0x000000ff;
- tmpptr <<= 8;
- dmaptr |= tmpptr;
- tmpptr = *dmalow;
- tmpptr &= 0x000000ff;
- dmaptr |= tmpptr;
-
- delay();
- Super(ostack); /* back to user mode */
-
- if (dmaptr != buf)
- break;
- } else { /* rdsects return an error */
- if (tsterr(ret) == OK) {
- break;
- }
- }
- }
-
- if (ret == MDMCHGD) /* check if error occurred */
- return (ret);
-
- /* Determine if media is MFM or RLL */
- if (i < 20)
- msiz = (SECTOR)head * (SECTOR)cyl * RLL;
- }
-
- if (size != msiz)
- ret = ERROR;
- else
- ret = OK;
-
- return (ret);
- }
-
-
- /*
- * Chkparm()
- * Check if given logical device has the asssumed parameters.
- * Assumptions are:
- * - 512 bytes/sector
- * - 2 sectors/cluster
- * - 1 reserved sector
- * - 2 FATs
- *
- * Input:
- * ldev - logical device number ('C' -> 'P').
- *
- * Return:
- * OK - parameters of partition match the assumptions
- * ERROR - something went wrong.
- *
- * Comment:
- * Number of FATs is assumed to be 2. Cannot check this
- * because previous version of HDX did not put that in the boot
- * sector.
- */
- chkparm(ldev)
- int ldev;
- {
- char bs[512]; /* boot sector */
- BOOT *boot; /* boot structure */
- UWORD bps, res, siz; /* bytes/sector, num reserved sectors, ldev size */
- int ret;
-
- if ((ret = rdsects(ldev, 1, bs, (SECTOR)0)) != 0) {
- if (tsterr(ret) != OK)
- err(bootread);
- ret = ERROR;
- goto parmend;
- }
-
- boot = (BOOT *)bs;
- gw((UWORD *)&boot->b_bps, &bps); /* what is number bytes/sector? */
- gw((UWORD *)&boot->b_res, &res); /* what is num of reserved sectors? */
- gw((UWORD *)&boot->b_nsects, &siz); /* what is size of partition */
- if (bps % BPS /* bytes per sector == ratio of 512 ? */
- || res != 1) { /* num sectors reserved == 1 ? */
- ret = ERROR; /* Nope, different from assumptions */
- goto parmend;
- }
-
- /* Check if sectors per cluster make sense */
- if (boot->b_spc != 2) {
- ret = ERROR;
- goto parmend;
- }
-
- ret = OK; /* If yes, return OK */
-
- parmend:
- return ret;
- }
-
-
- ichkparm(ldev)
- int ldev;
- {
- char bs[512]; /* boot sector */
- BOOT *boot; /* boot structure */
- UWORD bps, res, siz; /* bytes/sector, num reserved sectors, ldev size */
- int ret;
-
- if ((ret = rdsects(ldev, 1, bs, (SECTOR)0)) != 0) {
- if (tsterr(ret) != OK)
- err(bootread);
- ret = ERROR;
- goto parmend;
- }
-
- boot = (BOOT *)bs;
- gw((UWORD *)&boot->b_bps, &bps); /* what is number bytes/sector? */
- gw((UWORD *)&boot->b_res, &res); /* what is num of reserved sectors? */
- gw((UWORD *)&boot->b_nsects, &siz); /* what is size of partition */
- if (bps != 512 /* bytes per sector == 512 ? */
- || res != 1) { /* num sectors reserved == 1 ? */
- ret = ERROR; /* Nope, different from assumptions */
- goto parmend;
- }
-
- /* Check if sectors per cluster make sense */
- if ((siz >= 0x8000L && boot->b_spc != 4) ||
- (siz < 0x8000L && boot->b_spc != 2)) {
- ret = ERROR;
- goto parmend;
- }
-
- ret = OK; /* If yes, return OK */
-
- parmend:
- return ret;
- }
-
-
- /*
- * Get dev's root block.
- *
- */
- getroot(dev, buf, sect)
- int dev;
- char *buf;
- SECTOR sect;
- {
- return rdsects(dev, 1, buf, sect);
- }
-
-
- /*
- * Put dev's root block.
- *
- */
- putroot(dev, buf, sect)
- int dev;
- char *buf;
- SECTOR sect;
- {
- return wrsects(dev, 1, buf, sect);
- }
-
-
- /*
- * Read sector(s) from dev.
- *
- * Input:
- * dev - device number (logical or physical).
- * num - number of sectors to read.
- * buf - buffer to write data read.
- * sect - starting sector number to read from.
- *
- * Return:
- * errnum - 0: if read is successful.
- * an error code: if read is unsuccessful.
- */
- rdsects(dev, num, buf, sect)
- int dev; /* device number (logical or physical) */
- UWORD num; /* number of sectors to read */
- char *buf;
- SECTOR sect; /* starting sector to read from */
- {
- int errnum;
-
- if (log2phys(&dev, §) < 0)
- return ERROR;
-
- ostack = Super(NULL);
- errnum = hread(sect, num, buf, (UWORD)dev);
- if (errnum == 04) { /* the drive is stop */
- delay();
- stunt(dev, 1); /* start the drive */
- delay();
- errnum = hread(sect, num, buf, (UWORD)dev);
- }
- delay();
- Super(ostack);
-
- if (errnum > 0) {
- errnum = errcode(dev);
- }
-
- return errnum; /* return the error code */
- }
-
-
- /*
- * Write sector(s) to dev.
- *
- * Input:
- * dev - device number (logical or physical).
- * num - number of sectors to write.
- * buf - buffer with data to be written.
- * sect - starting sector number to write to.
- *
- * Return:
- * errnum - 0: if write is successful.
- * an error code: if write is unsuccessful.
- */
- wrsects(dev, num, buf, sect)
- int dev; /* device number (logical or physical */
- UWORD num; /* number of sectors to write */
- char *buf; /* buffer with data to be written */
- SECTOR sect; /* starting sector to write to */
- {
- int errnum;
-
- if (log2phys(&dev, §) < 0)
- return ERROR;
-
- ostack = Super(NULL);
- errnum = hwrite(sect, num, buf, (UWORD)dev);
- if (errnum == 04) { /* the drive is stop */
- delay();
- stunt(dev, 1); /* start the drive */
- delay();
- errnum = hwrite(sect, num, buf, (UWORD)dev);
- }
- delay();
- Super(ostack);
-
- if (errnum > 0) {
- errnum = errcode(dev);
- }
-
- return errnum;
- }
-
-
- /*
- * Zero range of sectors on dev.
- *
- */
- zerosect(dev, start, count)
- int dev;
- SECTOR start;
- UWORD count;
- {
- char *zbuf;
- int v;
- UWORD i;
-
- if ((zbuf = (char *)mymalloc(ZBUFSIZ)) <= 0)
- return err(nomemory);
-
- if (log2phys(&dev, &start) < 0) {
- free(zbuf);
- return ERROR;
- }
-
- fillbuf(zbuf, (long)ZBUFSIZ, 0L);
-
- while (count)
- {
- if (count > ZCOUNT)
- i = ZCOUNT;
- else i = count;
-
- if ((v = wrsects(dev, i, zbuf, start)) != 0)
- break;
- start += i;
- count -= i;
- }
- free(zbuf);
-
- return v;
- }
-