Ultrix-3.1/src/cmd/el/elp2.c

Compare this file to the similar file:
Show the results in this format:


/**********************************************************************
 *   Copyright (c) Digital Equipment Corporation 1984, 1985, 1986.    *
 *   All Rights Reserved. 					      *
 *   Reference "/usr/src/COPYRIGHT" for applicable restrictions.      *
 **********************************************************************/

static char Sccsid[] = "@(#)elp2.c	3.1	3/26/87";
/*
 * ULTRIX-11 error log report program (elp) - PART 2
 * Fred Canter 7/2/83
 *
 * The input for the report is taken from the current
 * error log or the optional [file].
 *
 * PART 2 of elp does the following:
 *
 * 1.	Contains the error log read buffer.
 *
 * 2.	Contains the error type heading and
 *	device name text string arrays.
 *
 * 3.	Contains all variables and arrays used
 *	for maintaining the hard and soft error counts.
 *
 * 4.	Counts the number of occurences of each type
 *	of error and counts the number of hard and
 *	soft errors for device errors.
 *
 * 5.	Prints the summary portion of the error log report.
 *
 */

#include "elp.h"	/* must be first (param.h) */
#include <sys/devmaj.h>
#include <sys/tmscp.h>	/* must preceed errlog.h (EL_MAXSZ) */
#include <sys/ra_info.h>
#include <sys/errlog.h>
#include <stdio.h>
#include <time.h>

/*
 * Error log input file read buffer.
 */

int	buf[256+1];

/*
 * Error type header messages
 */

char	*et_head[]
{
	"dummy",
	"ERROR LOGGING STARTUP",
	"ERROR LOGGING SHUTDOWN",
	"TIME CHANGE",
	"STRAY INTERRUPT",
	"STRAY VECTOR",
	"MEMORY PARITY ERROR",
	"BLOCK I/O DEVICE ERROR",
	0
};
/*
 * Device name header messages
 */

char	*dntab[]
{
	"(RK11) - RK03/RK05",
	"(RP11) - RP03",
	"(MSCP) - RC25/RX33/RX50/RD31-32/RD51-54/RA60/RA80/RA81",  /* default */
	"(RL11) - RL01/RL02",
	"(RX211) - RX02",
	"(TM11) - TU10/TE10/TS03",
	"(TMSCP) - TK50/TU81",
	"(TS11/TSV05/TSU05/TU80/TK25)",
	"(RH11/RH70 - TM02/3) - TU16/TE16/TU77",
	"(first  - RH11/RH70) - RP04/5/6, RM02/3/5, ML11",
	"(second - RH11/RH70) - RP04/5/6, RM02/3/5, ML11",
	"(RK611/RK711) - RK06/RK07",
	"(third  - RH11/RH70) - RP04/5/6, RM02/3/5, ML11",
	" CONSOLE",
	" PC11",
	" LP11",
	" DC11",
	" DH11",
	" DP11",
	" DHU11/DHV11",
	" DN11",
	" DZ11/DZV11/DZQ11",
	" DU11",
	0
};
/*
 * MSCP controller type name string,
 * setup by setrat(),
 * index is controller number.
 */
char	*ra_ctn[MAXUDA];
int	ra_cid[MAXUDA];	/* Numerical controller ID */
/*
 * MSCP controller type name strings,
 * index is UQPORT controller type ID.
 */
char	*radntab[] =
{
	"(UDA50) - RA60/RA80/RA81",
	"(KLESI) - RC25",
	"(RUX1) - RX50",
	"UNKNOWN",
	"UNKNOWN",	/*	"(KDA25) - RA60/RA80/RA81",	*/
	"UNKNOWN",
	"(UDA50A) - RA60/RA80/RA81",
	"(RQDX1) - RX33/RX50/RD31/RD32/RD51/RD52/RD53/RD54",
	"UNKNOWN",
	"UNKNOWN",
	"UNKNOWN",
	"UNKNOWN",
	"UNKNOWN",
	"(KDA50) - RA60/RA80/RA81",
	"(RQDX3) - RX33/RX50/RD31/RD32/RD51/RD52/RD53/RD54",
	"UNKNOWN",
};

/*
 * Hard and soft error count arrays.
 * The (ht) has 64 units, (rl) has 4, rest have 8.
 * The (rl) is treated as if it had 8 units to save code.
 *
 */

int	rk_hec[8];
int	rk_sec[8];
int	rp_hec[8];
int	rp_sec[8];
int	ra_hec[MAXUDA][8];
int	ra_sec[MAXUDA][8];
int	rl_hec[8];
int	rl_sec[8];
int	rx_hec[8];
int	rx_sec[8];
int	tm_hec[8];
int	tm_sec[8];
int	tk_hec[8];
int	tk_sec[8];
int	ts_hec[8];
int	ts_sec[8];
int	ht_hec[64];
int	ht_sec[64];
int	hp_hec[8];
int	hp_sec[8];
int	hm_hec[8];
int	hm_sec[8];
int	hk_hec[8];
int	hk_sec[8];
int	hj_hec[8];
int	hj_sec[8];

/*
 * These arrays hold the ECC recovered and retry 
 * recovered soft error counts for the hp, hm, hj, hk disks.
 */

int	hp_ecce[8];
int	hp_rtce[8];
int	hm_ecce[8];
int	hm_rtce[8];
int	hj_ecce[8];
int	hj_rtce[8];
int	hk_ecce[8];
int	hk_rtce[8];

/*
 * Various time buffers & pointers.
 */

time_t	timbuf;
long	lotim, hitim;
struct tm *tl, *th;

/*
 * Error log summary report
 * Called by main() in PART 1 (elp1.c)
 */

ersum(fi, filen)
{

	register struct el_rec *erp;
	register char *ebp;
	int	*ec;
	daddr_t bn;
	int	lim, rn;
	int	elfull;
	int	i, j, f, ft;
	int	rtc;
	int	bde_ec;
	int	etyp, maj, dn, cn;
	char	sz;
	int	dskip;

/*
 * Read thru the error log and count
 * the number of occurrences of each error type.
 */

	elfull = bn = 0;
	hitim = 0;
	ft = 0;
	bde_ec = 0;
	badrn = -1;
	if(!fnflag)
		lseek(fi, (long)((bn+el_sb)*512), 0);
ecloop:
	if(!fnflag)
		if((bn + el_sb) >= (el_sb + el_nb)) {
			elfull++;
			bn--;
			goto eclend;
			}
	if(read(fi, (char *)&buf, 512) != 512) {
	if(fnflag) {
		elfull++;
		bn--;
		goto eclend;
		}
	rderr:
		fprintf(stderr,"\nelp: read error bn = %D\n", bn+el_sb);
		exit(1);
		}
	ebp = &buf;
	erp = ebp;
	rn = 0;
	while((ebp < &buf[256]) && ((etyp = erp->er_hdr.e_type) != E_EOB)) {
/*
 * If record size is odd, zero, or
 * greater than the maximum size
 * treat it is end of file.
 */
		if(etyp != E_EOF)
		{
		sz = erp->er_hdr.e_size;
		if((sz == 0) || (sz & 1) | (sz > EL_MAXSZ)) {
		fprintf(stderr, "\nelp: Error record with invalid size\n     ");
		  fprintf(stderr, "bn = %D, rn = %d, size = %d bytes",bn,rn,sz);
			fprintf(stderr, "\n     Assuming end of file\n");
			badbn = bn;
			badrn = rn;
			badet = etyp;
			badsz = sz;
			goto eclend;
			}
		}
/*
 * If date flag is set use specified date/time limits,
 * otherwise use first to last date.
 */

		dskip = 0;
		if(dflag) {
			timbuf = erp->er_hdr.e_time;
			tl = localtime(&timbuf);
			elrtim[0] = tl->tm_sec;
			elrtim[1] = tl->tm_min;
			elrtim[2] = tl->tm_hour;
			elrtim[3] = tl->tm_mday;
			elrtim[4] = tl->tm_mon;
			elrtim[5] = tl->tm_year;
			elrtim[5] += 1900;
	
		/* if error log record date/time is out of range, ignore it */
			if(gte(&elrtim, &timl) && lte(&elrtim, &timh)) {
				if(!ft) {	/* set range to time of first error */
					lotim = timbuf;
					hitim = timbuf;
					ft++;
					}
				} else
					dskip++;
			}
		switch(etyp) {
		case E_EOF:	/* end of error log */
			if(bn == 0 && rn == 0) {
			fprintf(stderr,"\nelp: no errors have been logged\n");
				exit(1);
				}
			goto eclend;
		case E_SU:	/* startup */
				/* First record will always be a startup, */
				/* save its time. */
			if(bn == 0 && rn == 0 && !dflag)
				lotim = erp->er_hdr.e_time;
			/*
			 * Set MSCP disk controller type ID,
			 * UDA50/UDA50A/RQDX1/RQDX3/RUX1/KLESI message selection.
			 */
			setrat(erp->er_body.su.e_mccw);
		case E_SD:	/* shutdown */
		case E_TC:	/* time change */
		case E_SI:	/* stray interrupt */
		case E_SV:	/* stray vector */
		case E_MP:	/* memory parity */
			if(!dskip)
				elc[etyp].tec++;
			break;
		case E_BD:	/* block I/O device */
			if(dskip)
				break;
			bde_ec++;
			maj = (erp->er_body.bd.bd_dev >> 8) & 077; /* maj dev */
			dn = erp->er_body.bd.bd_dev;
			cn = (dn >> 6) & 3;	/* used with MSCP disks only */
			if(maj >= nblkdev) { 	/* RAW device */
				for(etyp=E_BD; etyp<(E_BD+nblkdev); etyp++)
					if(elc[etyp].rmaj == maj)
						break;
				if(maj == HT_RMAJ)
					dn &= 077;	/* unit number */
				else if(maj == RP_RMAJ
					|| maj == HP_RMAJ
					|| maj == HM_RMAJ
					|| maj == HJ_RMAJ
					|| maj == RA_RMAJ
					|| maj == RL_RMAJ
					|| maj == HK_RMAJ)
						dn = (dn >> 3) & 7;
				else if(maj == HX_RMAJ)
					dn &= 1;
				else
					dn &= 7;
			} else {				/* BLOCK dev */
				for(etyp=E_BD; etyp<(E_BD+nblkdev); etyp++)
					if(elc[etyp].bmaj == maj)
						break;
				if(maj == HT_BMAJ)
					dn &= 077;
				else if(maj == RP_BMAJ
					|| maj == HP_BMAJ
					|| maj == HM_BMAJ
					|| maj == HJ_BMAJ
					|| maj == RL_BMAJ
					|| maj == RA_BMAJ
					|| maj == HK_BMAJ)
						dn = (dn >> 3) & 7;
				else if(maj == HX_BMAJ)
					dn &= 1;
				else
					dn &= 7;
				}
			rtc = erp->er_body.bd.bd_errcnt;	/* retry count */
			/* special case for MSCP disks (like everything else) */
			if(elc[etyp].bmaj == RA_BMAJ) {
				if((rtc==0) || (rtc > elc[etyp].rtc))
					ra_hec[cn][dn]++;  /* hard error */
				else
					ra_sec[cn][dn]++;  /* soft error */
				elc[etyp].tec++;	/* total error count */
				break;
			}
			if((rtc == 0) || (rtc > elc[etyp].rtc)) { /* hard err */
				ec = elc[etyp].hec;
				*(ec + dn) += 1;
			} else {				/* soft err */
				ec = elc[etyp].sec;
				*(ec + dn) += 1;
				if(elc[etyp].bmaj == HP_BMAJ) {	/* HP soft */
				    if ((erp->er_body.bd.bd_flags & E_READ)
				      && ((erp->devreg[6] & (DCK|ECH)) == DCK))
					  hp_ecce[dn]++;  /* ecc recovered */
				    else
					  hp_rtce[dn]++;  /* retry recovered */
				}
				if(elc[etyp].bmaj == HM_BMAJ) {	/* HM soft */
				    if ((erp->er_body.bd.bd_flags & E_READ)
				      && ((erp->devreg[6] & (DCK|ECH)) == DCK))
					  hm_ecce[dn]++;  /* ecc recovered */
				    else
					  hm_rtce[dn]++;  /* retry recovered */
				}
				if(elc[etyp].bmaj == HJ_BMAJ) {	/* HJ soft */
				    if ((erp->er_body.bd.bd_flags & E_READ)
				      && ((erp->devreg[6] & (DCK|ECH)) == DCK))
					  hj_ecce[dn]++;  /* ecc recovered */
				    else
					  hj_rtce[dn]++;  /* retry recovered */
				}
				if(elc[etyp].bmaj == HK_BMAJ) {	/* HK soft */
				    if ((erp->er_body.bd.bd_flags & E_READ)
				      && ((erp->devreg[6] & (DCK|ECH)) == DCK))
					  hk_ecce[dn]++;  	/* ecc recovered */
				    else
					  hk_rtce[dn]++;  	/* retry recovered */
				}
			}
			elc[etyp].tec++;	/* total error count */
			break;
		default:
	   fprintf(stderr,"\nelp: Error record with invalid error type\n     ");
	      fprintf(stderr,"bn = %D, rn = %d, error type = %d", bn,rn,etyp);
		fprintf(stderr, "\n     Assuming end of file\n");
			badbn = bn;
			badrn = rn;
			badet = etyp;
			badsz = erp->er_hdr.e_size;
			goto eclend;
		}

	if(!dflag || !dskip) {
		timbuf = erp->er_hdr.e_time;
		if(timbuf < lotim)
			lotim = timbuf;
		if(timbuf > hitim)
			hitim = timbuf;
		}
around:
	ebp += erp->er_hdr.e_size;	/* move pointer to next record */
	erp = ebp;
	rn++;
	}
	bn++;
	goto ecloop;
eclend:

/* get the current time & print the report header msg's */

	time(&timbuf);
	printf("\nULTRIX-11 SYSTEM ERROR REPORT, taken on - %s\n",ctime(&timbuf));
	if(elfull)
		printf("\n****** This error log is full. ******\n\n");
	if(badrn >= 0) {
	    printf("\n****** Report terminated by a bad error record ! ******");
	    printf("\n\n****** Block number	%D	******", badbn);
	    printf("\n****** Record number	%d	******", badrn);
	    printf("\n****** Error type	%d	******", badet);
	    printf("\n****** Record size	%d	******\n", badsz);
		}
	printf("\nError type limitations: [ ");
	if(!etflag)
		printf("NONE ]");
	else if(et >= E_BD) {
		if((etcn < 0) || (etcn == MAXUDA))
			printf("%s ]", dntab[elc[et].edn]);
		else
			printf("%s ]", ra_ctn[etcn]);
		if(etdn >= 0)
			printf("\n\t\t\t[ unit %d only ]", etdn);
	} else
		printf("%s ]", et_head[elc[et].ehm]);
	if(rflag)
		printf("\n\t\t\t[ For block I/O devices, recovered errors only ]");
	if(uflag)
		printf("\n\t\t\t[ For block I/O devices, unrecovered errors only ]");
	printf("\n");
	printf("\nInput taken from\t%s\n", filen);
	if(!fnflag) {
		printf("Error log start block\t%D\n", el_sb);
		printf("Length in blocks\t%d\n", el_nb);
	printf("\nCurrent error log has %D of %d blocks used.\n", (bn+1), el_nb);
		}
	printf("\nREPORTED DATE/TIME RANGE: ");
	if(dflag)
		printf("[ only errors within specified limits ]\n\n");
	else
		printf("[ first error thru last error ]\n\n");
	printf("\t%.24s thru ", ctime(&lotim));
	printf("%s\n", ctime(&hitim));
	if(fflag)
		return;
	if(!etflag || (etflag && et == E_SU))
		printf("\nTOTAL startup\t\t= %d\n",elc[E_SU].tec);
	if(!etflag || (etflag && et == E_SD))
		printf("\nTOTAL shutdown\t\t= %d\n",elc[E_SD].tec);
	if(!etflag || (etflag && et == E_TC))
		printf("\nTOTAL time change\t= %d\n",elc[E_TC].tec);
	if(!etflag || (etflag && et == E_SI))
		printf("\nTOTAL stray interrupts\t= %d\n",elc[E_SI].tec);
	if(!etflag || (etflag && et == E_SV))
		printf("\nTOTAL stray vectors\t= %d\n",elc[E_SV].tec);
	if(!etflag || (etflag && et == E_MP))
		printf("\nTOTAL memory parity\t= %d\n",elc[E_MP].tec);
	if(!etflag || (etflag && et >= E_BD))
		printf("\nTOTAL block I/O errors\t= %d\n\n",bde_ec);
	for(i=0; i<nblkdev; i++) {
	    if(i == RA_BMAJ) {	/* yet another MSCP special case */
		for(cn=0; cn<MAXUDA; cn++) {
		    if((etcn >= 0) && (etcn != cn))
			continue;
		    f = 0;
		    for(j=0; j<8; j++) {
			if(!etflag || (etflag && et == (E_BD + i)))
			    if((etdn < 0) || (j == etdn))
			    {
			      if(ra_hec[cn][j] || ra_sec[cn][j]) {
				if(f==0) {
				      printf("\n%s\n", ra_ctn[cn]);
				      f++;
				}
			      printf("\n UNIT %d\n", j);
			      printf("\n\tHard errors\t\t= %d", ra_hec[cn][j]);
			      printf("\n\tSoft errors\t\t= %d", ra_sec[cn][j]);
			      printf("\n\n");
			      }
			    }
		    }
		}
		continue;
	    }
	    f = 0;
	    if(i == HT_BMAJ)
	    	lim = 64;
	    else
	    	lim = 8;
	    for(j=0; j<lim; j++) {
	        if(!etflag || (etflag && et == (E_BD + i)))
	    	if((etdn < 0) || (j == etdn))
	    	{
	    	if(elc[E_BD+i].hec[j] || elc[E_BD+i].sec[j]) {
	    	if(f == 0) {
	    		printf("\n%s\n", dntab[elc[E_BD+i].edn]);
	    		f++;
	    		}
	    	printf("\n UNIT %d\n", j);
	    	printf("\n\tHard errors\t\t= %d",elc[E_BD+i].hec[j]);
	    	printf("\n\tSoft errors\t\t= %d",elc[E_BD+i].sec[j]);
	    	if(i == HP_BMAJ)	/* hp ECC vs retry counts */
	    	{
	    	printf("\n\t(ECC   recovered)\t= %d",hp_ecce[j]);
	    	printf("\n\t(RETRY recovered)\t= %d",hp_rtce[j]);
	    	}
	    	if(i == HM_BMAJ)	/* hm ECC vs retry counts */
	    	{
	    	printf("\n\t(ECC   recovered)\t= %d",hm_ecce[j]);
	    	printf("\n\t(RETRY recovered)\t= %d",hm_rtce[j]);
	    	}
	    	if(i == HJ_BMAJ)	/* hj ECC vs retry counts */
	    	{
	    	printf("\n\t(ECC   recovered)\t= %d",hj_ecce[j]);
	    	printf("\n\t(RETRY recovered)\t= %d",hj_rtce[j]);
	    	}
	    	if(i == HK_BMAJ)	/* hk ECC vs retry counts */
	    	{
	    	printf("\n\t(ECC   recovered)\t= %d",hk_ecce[j]);
	    	printf("\n\t(RETRY recovered)\t= %d",hk_rtce[j]);
	    	}
	    	printf("\n\n");
	    	}
	        }
	    }
	}
}

/* return 1 if time1 is >= time2 */

gte(t1,t2)
int *t1, *t2;
{
	register int q;

	for(q=5; q >= 0; q--) {
		if(*(t1 + q) < *(t2 + q))
			return(0);
		else if(*(t1 + q) > *(t2 + q))
			return(1);
			}
	return(1);
}

/* return 1 if time1 is <= time2 */

lte(t1, t2)
int *t1, *t2;
{
	register int q;

	for(q=5; q >= 0; q--) {
		if(*(t1 + q) > *(t2 + q))
			return(0);
		else if(*(t1 + q) < *(t2 + q))
			return(1);
			}
	return(1);
}

/*
 * Setup the MSCP controller type name strings
 * from the config word in the startup record.
 */

setrat(mct)
{
	register int i, j;

	for(i=0; i<MAXUDA; i++) {
		j = (mct >> (i * 4)) & 017;
		ra_cid[i] = j;	/* save cntlr ID */
		if(j == 017)
			ra_ctn[i] = "";
		else
			ra_ctn[i] = radntab[j];
	}
/*
 * Set the MSCP error type controller number
 * from the saved controller type.
 * etct - 0=ra, 1=rc, 2=rd, 3=rx
 */
	if(etct >= 0) {
		etcn = MAXUDA;
		for(i=0; i<MAXUDA; i++) {
			switch(etct) {
			case 0:
				if((ra_cid[i]==UDA50) || (ra_cid[i]==UDA50A) ||
/*				   (ra_cid[i]==KDA50) || (ra_cid[i]==KDA25)) */
				   (ra_cid[i]==KDA50))
					etcn = i;
				break;
			case 1:
				if(ra_cid[i] == KLESI)
					etcn = i;
				break;
			case 2:
				if((ra_cid[i] == RQDX1) || (ra_cid[i] == RQDX3))
					etcn = i;
				break;
			case 3:
				if((ra_cid[i] == RQDX1) ||
				   (ra_cid[i] == RQDX3) ||
				   (ra_cid[i] == RUX1))
					etcn = i;
				break;
			}
		}
	} else
		etcn = -1;
}