/* sect.c */ #include "obdefs.h" #include "osbind.h" #include "defs.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 */ extern long ostack; /* old stack pointer */ extern UWORD errcode(); /* function to return error code */ /* * Logical-to-dev+partition mapping table. */ int nlogdevs; /* # logical devices */ LOGMAP logmap[MAXLOGDEVS]; /* logical dev map */ int livedevs[MAXPHYSDEVS]; /* live devs flags; 1: device is alive */ /* * Rebuild logical-to-physical mapping * by reading and interpreting the root * blocks for all physical devs. * */ rescan(flag) int flag; /* 0: don't report medium change error; */ /* non-0: report medium change error; */ { int dev; char buf[512]; int partno, ret; PART partinfo[NPARTS]; /* disable all logical and physical devs */ for (dev = 0; dev < MAXLOGDEVS; ++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; for (dev = 0; dev < MAXPHYSDEVS; ++dev) { if ((ret = getroot(dev, buf)) < 0) { 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))) { /* try again */ if (ret > 0 && flag && tsterr(ret) == OK) return ERROR; continue; } } livedevs[dev] = 1; gpart(buf, &partinfo[0]); for (partno = 0; partno < NPARTS; ++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') { if (nlogdevs >= MAXLOGDEVS) return err(manyldev); 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; } } } } return OK; } /* * 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 < MAXLOGDEVS; 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 <= 7) return OK; dev = toupper(dev); if (dev >= 'C' && dev <= 'P') { 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 <= 'P') { 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 <= 'P') { 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; int cyl, head; SECTOR size, msiz; /* size of media */ char buf[512], sendata[16]; 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 */ ret = md_sense(dev, sendata); delay(); Super(ostack); if (ret != 0) { return ERROR; } /* 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 != 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) int dev; char *buf; { return rdsects(dev, 1, buf, (SECTOR)0); } /* * Put dev's root block. * */ putroot(dev, buf) int dev; char *buf; { return wrsects(dev, 1, buf, (SECTOR)0); } /* * 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); 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); 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; }