File:  [MW Coherent from dump] / coherent / f / tmp / install / hdparms.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Wed May 29 04:56:40 2019 UTC (7 years, 2 months ago) by root
Branches: MarkWilliams, MAIN
CVS tags: relic, HEAD
coherent

/*
 * File:	hdparms.c
 *
 * Last Hacked:	06/25/92
 *
 * Purpose:	display and modify hard drive parameters
 *
 *	Called by "mkdev" command or usable as stand-alone.
 *	Non-build version expects driver in /tmp/drv, which is where mkdev
 *	leaves it.
 *
 * Usage:	hdparms [-bfrs] devname ...
 *
 * Options:
 *	-b	Use special processing when invoked from /etc/build
 *	-f	Future Domain SCSI
 *	-r	Specified device controls root partition (implies -b)
 *	-s	Seagate SCSI
 */

/*
 * Includes.
 */
#define __KERNEL__ 1  /* to get buf.h via scsiwork.h */

#include <stdio.h>
#include <sys/fdisk.h>
#include <sys/hdioctl.h>
#include <sys/stat.h>
#include <sys/scsiwork.h>

#include "build0.h"

/*
 * Definitions.
 *	Constants.
 *	Macros with argument lists.
 *	Typedefs.
 *	Enums.
 */
#define	USAGEMSG	"Usage:\t/etc/hdparms [ -bfrs ] device...\n"
#define OPENMODE	2	/* Default open mode: read/write. */
#define BUFLEN		40
#define DEV_SCSI_ID(dev)	((dev >> 4) & 0x0007)
#define	VERSION		"V2.0"		/* version number */

/*
 * Functions.
 *	Import Functions.
 *	Export Functions.
 *	Local Functions.
 */
#if DEFAULT_PARMS
static void cam_parms();
static void fd_parms();
#endif
static void getuint();
static int hdparms();

/*
 * Global Data.
 *	Import Variables.
 *	Export Variables.
 *	Local Variables.
 */
static int bflag;	/* 1 for call via /etc/build */
static int fflag;	/* 1 for Future Domain SCSI */
static int rflag;	/* 1 for rootdev */
static int sflag;	/* 1 for Seagate SCSI */

/*
 * main()
 */
main(argc, argv)
int argc;
char *argv[];
{
	unsigned char *s;
	int success = 1;

	argv0 = argv[0];
	usagemsg = USAGEMSG;
	if (argc > 1 && argv[1][0] == '-') {
		for (s = &argv[1][1]; *s; ++s) {
			switch(*s) {
			case 'b':
				++bflag;
				break;
			case 'f':
				++fflag;
				break;
			case 'r':
				++rflag;
				++bflag;
				break;
			case 's':
				++sflag;
				break;
			default:
				usage();
			}
		}
		--argc;
		++argv;
	}

	while (--argc > 0) {
		success &= hdparms(argv[1]);
		++argv;
	}

	/*
	 * Exit with nonzero value if any call to hdparms() failed.
	 */
	exit(success == 0);
}

/*
 * hdparms()
 *
 * Return 0 if error occurred, else 1.
 */
static int hdparms(devname)
unsigned char *devname;
{
	int fd;
	hdparm_t parms;
	int ret = 0;
	struct stat dvstat;
	int s_id;		/* SCSI id */
	uint pl;		/* offset of device entry in drv_parm_ */
	unsigned char ss_patch[60];
	unsigned char * drv = "/drv/ss";
	unsigned char cmd[80];
	FILE * fp;

	if ((fd = open(devname, OPENMODE)) < 0) {
		printf("Can't open %s.\n", devname);
		goto noclose_fd;
	}

	if (sflag || fflag)
		if (stat(devname, &dvstat) != 0) {
			printf("Can't stat %s.\n", devname);
			goto close_fd;
		} else {
			s_id = DEV_SCSI_ID(dvstat.st_rdev);
			pl = sizeof(_drv_parm_t) * s_id;
		}

	if (ioctl(fd, HDGETA, (char *)(&parms)) == -1)
		printf("Can't get parameters for %s.\n", devname);
	else {
		uint ncyls, nheads, nspt;
		unsigned long nsectors;

		ncyls = (parms.ncyl[1] << 8) | parms.ncyl[0];
		nheads = parms.nhead;
		nspt = parms.nspt;
		nsectors = (unsigned long)ncyls * (unsigned long)nheads * (unsigned long)nspt;

printf("\nHere are the current parameters for SCSI device %d:\n", s_id);
printf("Number of cylinders = %d\n", ncyls);
printf("Number of heads = %d\n", nheads);
printf("Number of sectors per track = %d\n", nspt);

printf(
"\nIf the values above do not agree with those used by your host adapter's BIOS"
"\nprogramming, you will not be able to boot COHERENT from this hard drive.\n");

		if (ncyls > 1024) {
printf(
"\nThis device has more than 1024 cylinders.  In order to use the entire drive"
"\nfrom COHERENT, and possibly to be compatible with other operating systems,"
"\nyou will need to enter a set of translation-mode parameters.  Enter the"
"\nparameters your BIOS uses.  You can accept the default values shown by"
"\npressing <Enter> at each prompt.\n\n");
#if DEFAULT_PARMS
			if (fflag)
				fd_parms(&ncyls, &nheads, &nspt);
			else
				cam_parms(&ncyls, &nheads, &nspt);
#endif				
		}

		if (yes_no("Do you want to modify drive parameters")) {
			getuint(&ncyls, "Number of cylinders");
			getuint(&nheads, "Number of heads");
			getuint(&nspt, "Number of sectors per track");

			parms.ncyl[1] = ncyls >> 8;
			parms.ncyl[0] = ncyls & 0xFF;
			parms.nhead = nheads;
			parms.nspt = nspt;

			if (ioctl(fd, HDSETA, (char *)(&parms)) == -1)
printf("Couldn't write new parameters for %s.\n", devname);
			else {
printf("New parameters written for %s.\n", devname);
				ret = 1;
			}

			/* Prepare to patch "ss" driver. */
			if (sflag || fflag) {
				sprintf(ss_patch,
					"drv_parm+%d=%d drv_parm+%d=0x%04x",
					pl, ncyls, pl+sizeof(int),
					(nspt<<8) + nheads);

				if (bflag) {

					/*
					 * Second kernel.
					 * Write PATCHFILE which is run by build.
					 */
					fp = fopen(PATCHFILE, "a");
fprintf(fp, "/conf/patch /mnt/coherent %s\n", ss_patch);
					fclose(fp);

					/* Third kernel. */
{
	char line[120];
	char tag[40];

	sprintf(line, "_TAG(SD%d)\t{ %d, %d, %d },",
	  s_id, ncyls, nspt, nheads);
	sprintf(tag, "SD%d", s_id);
	cohtune_ent("ss", tag, line);
}

				}
			}

		} else
			ret = 1;
	}

close_fd:
	close(fd);

noclose_fd:
	return ret;
}

/*
 * getuint()
 *
 * get unsigned integer value - display prompt with default value
 */
static void getuint(np, prompt)
uint * np;
unsigned char * prompt;
{
	unsigned char buf[BUFLEN];

	printf("%s [%d]: ", prompt, *np);
	fgets(buf, BUFLEN, stdin);
	sscanf(buf, "%d", np);
}

#if DEFAULT_PARMS
/*
 * cam_parms()
 *
 * Use CAM algorithm to compute new drive parameters which will keep
 * number of cylinders under 1024.
 */
static void cam_parms(p_ncyls, p_nheads, p_nspt)
uint * p_ncyls, * p_nheads, * p_nspt;
{
	unsigned long capacity, ncyls, nheads, nspt;
	unsigned long ntracks, nsph, nspc;

	capacity = (unsigned long)*p_ncyls * (unsigned long)*p_nheads * (unsigned long)*p_nspt;
	if (capacity == 0L)
		goto frotz;
	ncyls = 1024L;
	nspt = 62L;
	nsph = ncyls * nspt;
	nheads = capacity / nsph;

	if (capacity % nsph) {
		nheads++;
		ntracks = ncyls * nheads;
		nspt = capacity / ntracks;

		if (capacity % ntracks) {
			nspt++;
			nspc = nheads * nspt;
			ncyls = capacity / nspc;
		}
	}

	*p_ncyls = ncyls;
	*p_nheads = nheads;
	*p_nspt = nspt;
frotz:
	return;
}

/*
 * fd_parms()
 *
 * Use Future Domain algorithm to compute new drive parameters which will
 * keep number of cylinders under 1024.
 */
static void fd_parms(p_ncyls, p_nheads, p_nspt)
uint * p_ncyls, * p_nheads, * p_nspt;
{
	unsigned long capacity, ncyls, nheads, nspt;
	unsigned long ntracks, foo, nspc;

	capacity = (unsigned long)*p_ncyls *
	  (unsigned long)*p_nheads * (unsigned long)*p_nspt;
	if (capacity == 0L)
		goto frotz;
	nspt = 17;	/* first try 17 spt */
	while (1) {
		foo = capacity / 1024;
		nheads = (foo / nspt) + 1;
		nspc = nheads * nspt;
		ncyls = capacity / nspc;
		ntracks = nheads * ncyls;
		if (ntracks < 32768L)
			break;
		if (nspt == 17)
			nspt = 34;	/* after 17, try 34 spt */
		else if (nspt == 34)
			nspt = 63;	/* after 34, try 63 spt */
		else
			break;
	}

	*p_ncyls = ncyls;
	*p_nheads = nheads;
	*p_nspt = nspt;
frotz:
	return;
}
#endif

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.