static char rcsid[] = "$Header: iostat.c,v 800.1 85/10/24 12:52:15 root Exp $";
static char sccsid[]="%W% %Y% %Q% %G%";

/****************************************************************************

                          Copyright  1982

               VALID  LOGIC  SYSTEMS  INCORPORATED

This listing contains confidential proprietary information which is not to
be disclosed to unauthorized persons without written consent of an officer
of Valid Logic Systems Incorporated.

The copyright notice appearing above is included to provide statutory
protection in the event of unauthorized or unintentional public disclosure.

*****************************************************************************/
#include <a.out.h>
#include <sys/param.h>

#define	HZ	60

int	bflg;
int	dflg;
int	iflg;
int	aflg;
int	sflg;
struct nlist nl[] = {
	"dk_busy", 0, 0,
#define DK_BUSY 0
	"io_info", 0, 0,
#define IO_INFO 1
	"dk_time", 0, 0,
#define DK_TIME 2
	"dk_numb", 0, 0,
#define DK_NUMB 3
	"dk_wds", 0, 0,
#define DK_WDS 4
	"tk_nin", 0, 0,
#define TK_NIN 5
	"tk_nout", 0, 0,
#define TK_NOUT 6
	"\0\0\0\0\0\0\0\0", 0, 0
};
struct stats
{
	int	busy;
	long	etime[32];
	long	numb[6];
	long	wds[6];
	long	tin;
	long	tout;
} s, s1;

struct iostat {
	int	nbuf;
	long	nread;
	long	nreada;
	long	ncache;
	long	nwrite;
	long	bufcount[50];
} io_info, io_delta;
double	etime;

int	mf;

main(argc, argv)
char *argv[];
{
	extern char *ctime();
	register  i;
	int iter;
	double f1, f2;
	long t;

	nlist("/vmunix", nl);
	if(nl[0].n_type == -1) {
		printf("dk_busy not found in /vmunix namelist\n");
		exit(1);
	}
	mf = open("/dev/kmem", 0);
	if(mf < 0) {
		printf("cannot open /dev/kmem\n");
		exit(1);
	}
	iter = 0;
	while (argc>1&&argv[1][0]=='-') {
		if (argv[1][1]=='d')
			dflg++;
		else if (argv[1][1]=='s')
			sflg++;
		else if (argv[1][1]=='a')
			aflg++;
		else if (argv[1][1]=='i')
			iflg++;
		else if (argv[1][1]=='b')
			bflg++;
		argc--;
		argv++;
	}
	if(argc > 2)
		iter = atoi(argv[2]);
	if (!(sflg|iflg)) {
	if (bflg==0)
	printf("   DK                TTY        PERCENT\n");
	if (bflg==0)
	printf("   tpm     msps  mspt   ips   ops  user  nice systm  idle\n");
	}

loop:
	readstats(mf, &s);
/* fix up structure to look like single disk */
/*	s.numb[0] = s.numb[2];
	s.wds[0] = s.wds[2];
 */	s.numb[1] = s.numb[5];
	s.wds[1] = s.wds[5];
	s.numb[2] = 0;
	s.wds[2] = 0;
/* */
	for(i=0; i<46; i++) {
		t = s.etime[i];
		s.etime[i] -= s1.etime[i];
		s1.etime[i] = t;
	}
	t = 0;
	for(i=0; i<32; i++)
		t += s.etime[i];
	etime = t;
	if(etime == 0.)
		etime = 1.;
	if (bflg) {
		biostats();
		goto contin;
	}
	if (dflg) {
		long tm;
		time(&tm);
		printf("%s", ctime(&tm));
	}
	if (aflg)
		printf("%.2f minutes total\n", etime/(60.*HZ));
	if (sflg) {
		stats2(etime);
		goto contin;
	}
	if (iflg) {
		stats3(etime);
		goto contin;
	}
	etime /= HZ;
	for(i=0; i<1; i++)
		stats(i);
	f1 = s.tin;
	printf("%6.1f", f1/etime);
	f1 = s.tout;
	printf("%6.0f", f1/etime);
	for(i=0; i<4; i++)
		stat1(i*8);
	printf("\n");
contin:
	--iter;
	if(iter)
	if(argc > 1) {
		sleep(atoi(argv[1]));
		goto loop;
	}
}

/* usec per word for the various disks */
double	xf[] = {
	1.838,	/* DK */
	1.65,	/* XB */
};

stats(dn)
{
	register i;
	double f1, f2, f3;
	double f4, f5, f6;
	long t;

	t = 0;
	for(i=0; i<32; i++)
		if(i & (1<<dn))
			t += s.etime[i];
	f1 = t;
	f1 = f1/HZ;
	f2 = s.numb[dn];
	if(f2 == 0.) {
		printf("%6.0f  %7.1f%6.1f", 0.0, 0.0, 0.0);
		return;
	}
	f3 = s.wds[dn];
	f3 = f3*32.;
	f4 = xf[dn];
	f4 = f4*1.0e-6;
	f5 = f1 - f4*f3;
	f6 = f1 - f5;
	printf("%6.0f ", f2*60./etime);
	printf("%7.1f", f5*1000./f2);
	printf("%6.1f", f6*1000./f2);
}

stat1(o)
{
	register i;
	long t;
	double f1, f2, result;

	t = 0;
	for(i=0; i<32; i++)
		t += s.etime[i];
	f1 = t;
	if(f1 == 0.)
		f1 = 1.;
	t = 0;
	for(i=0; i<8; i++)
		t += s.etime[o+i];
	f2 = t;
	result = f2*100./f1;
	if (result < 0.)
		result = 0.;
	printf("%6.2f", result);
}

stats2(t)
double t;
{
	register i, j;

	for (i=0; i<4; i++) {
		for (j=0; j<8; j++)
			printf("%6.2f\n", s.etime[8*i+j]/(t/100));
		printf("\n");
	}
}

stats3(t)
double t;
{
	register i;
	double sum;

	t /= 100;
	printf("%6.2f idle\n", s.etime[24]/t);
	sum = 0;
	for (i=0; i<8; i++)
		sum += s.etime[i];
	printf("%6.2f user\n", sum/t);
	sum = 0;
	for (i=0; i<8; i++)
		sum += s.etime[8+i];
	printf("%6.2f nice\n", sum/t);
	sum = 0;
	for (i=0; i<8; i++)
		sum += s.etime[16+i];
	printf("%6.2f system\n", sum/t);
	sum = 0;
	for (i=1; i<8; i++)
		sum += s.etime[24+i];
	printf("%6.2f IO wait\n", sum/t);
	sum = 0;
	for (i=1; i<8; i++)
		sum += s.etime[i]+s.etime[i+8]+s.etime[i+16]+s.etime[i+24];
	printf("%6.2f DK active\n", sum/t);
/*	sum = 0;
	for (i=0; i<32; i++)
		if (i&01)
			sum += s.etime[i];
	printf("%6.2f RF active\n", sum/t);
	sum = 0;
	for (i=0; i<32; i++)
		if (i&02)
			sum += s.etime[i];
	printf("%6.2f RK active\n", sum/t);
	sum = 0;
	for (i=0; i<32; i++)
		if (i&04)
			sum += s.etime[i];
	printf("%6.2f RP active\n", sum/t);
*/}

biostats()
{
register i;

	lseek(mf,(long)nl[1].n_value, 0);
	read(mf, (char *)&io_info, sizeof(io_info));
	printf("%ld\t%ld\t%ld\t%ld\n",
	 io_info.nread-io_delta.nread, io_info.nreada-io_delta.nreada,
	 io_info.ncache-io_delta.ncache, io_info.nwrite-io_delta.nwrite);

	for(i=0; i<30; ) {
		printf("%ld",(long)io_info.bufcount[i]-io_delta.bufcount[i]);
		i++;
		if (i % 10 == 0)
			printf("\n");
		else printf("\t");
	}
	io_delta = io_info;
}



/* Read stat buffer info */
readstats(file, s)
int file;
struct stats *s;
{
	lseek(file, (long)nl[DK_BUSY].n_value, 0);
	read(file, (char *)&s->busy, sizeof s->busy);
	lseek(file, (long)nl[DK_TIME].n_value, 0);
	read(file, (char *)s->etime, sizeof s->etime);
	lseek(file, (long)nl[DK_NUMB].n_value, 0);
	read(file, (char *)s->numb, sizeof s->numb);
	lseek(file, (long)nl[DK_WDS].n_value, 0);
	read(file, (char *)s->wds, sizeof s->wds);
	lseek(file, (long)nl[TK_NIN].n_value, 0);
	read(file, (char *)&s->tin, sizeof s->tin);
	lseek(file, (long)nl[TK_NOUT].n_value, 0);
	read(file, (char *)&s->tout, sizeof s->tout);
}
