#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  COPYRIGHT MANIFEST README patchlevel.h Makefile scsiinfo.1
#   scsiinfo.c utils.c utils.h uscsi.h uscsi.c sunos4.h sunos5.h
#   sundev sundev/dmaga.h format.c format.h
# Wrapped by jdd@coke on Thu Aug  4 12:05:39 1994
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'COPYRIGHT' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'COPYRIGHT'\"
else
echo shar: Extracting \"'COPYRIGHT'\" \(911 characters\)
sed "s/^X//" >'COPYRIGHT' <<'END_OF_FILE'
X/*
X * Copyright University of Toronto 1993.
X * Written by John DiMarco 
X *
X * Permission is granted to anyone to use this software for any purpose on
X * any computer system, and to alter it and redistribute it freely, subject
X * to the following restrictions:
X *
X * 1. The author and the University of Toronto are not responsible 
X *    for the consequences of use of this software, no matter how awful, 
X *    even if they arise from flaws in it.
X *
X * 2. The origin of this software must not be misrepresented, either by
X *    explicit claim or by omission.  Since few users ever read sources,
X *    credits must appear in the documentation.
X *
X * 3. Altered versions must be plainly marked as such, and must not be
X *    misrepresented as being the original software.  Since few users
X *    ever read sources, credits must appear in the documentation.
X *
X * 4. This notice may not be removed or altered.
X */
END_OF_FILE
if test 911 -ne `wc -c <'COPYRIGHT'`; then
    echo shar: \"'COPYRIGHT'\" unpacked with wrong size!
fi
# end of 'COPYRIGHT'
fi
if test -f 'MANIFEST' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MANIFEST'\"
else
echo shar: Extracting \"'MANIFEST'\" \(493 characters\)
sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
XCOPYRIGHT		Copyright notice
XMANIFEST		This file
XMakefile		makefile
XREADME			Read this file first
Xpatchlevel.h		Patch level/version 
Xscsiinfo.1		scsiinfo manual page
Xscsiinfo.c		scsiinfo main source
Xsunos4.h		SunOS 4.1.x dependent code
Xsunos5.h		SunOS 5.x dependent code
Xuscsi.c			User SCSI routines
Xuscsi.h			header file for uscsi.c
Xutils.c			misc utilities
Xutils.h			header file for utils.c
Xsundev/dmaga.h		Empty file to fool cpp
Xformat.c		Format informat 
Xformat.h		header file for format.c
END_OF_FILE
if test 493 -ne `wc -c <'MANIFEST'`; then
    echo shar: \"'MANIFEST'\" unpacked with wrong size!
fi
# end of 'MANIFEST'
fi
if test -f 'README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'README'\"
else
echo shar: Extracting \"'README'\" \(5155 characters\)
sed "s/^X//" >'README' <<'END_OF_FILE'
XJuly 22, 1994 Release 3.3
X
XNew in release 3.3:
X	o -V flag
X	o -f output format changed slightly
X	o special-case code for Central Data SCSITerminal servers
X	o various bugfixes
X
XSCSIINFO displays information about SCSI devices attached to a given system,
Xas seen by the Sun ESP device driver. For each target known to the SCSI host
Xadapter, scsinfo reports whether it is synchronous or asynchronous, whether
Xor not the tranfers to/from the target are clean or susceptible to noise, and
Xwhether or not the target can disconnect and reconnect. When a target
Xsupports synchronous transfer, the negotiated maximum transfer rate (in
XMB/sec) is reported.
X
XIn version 3.0 and up, scsiinfo supports querying SCSI disks for geometry and
Xformatting information, and optionally generates a format.dat entry based
Xon these values.
X
XIn version 2.0 and up, scsinfo supports querying SCSI devices for vendor,
Xproduct, and revision information, in the style of the Openboot prom's
Xprobe-scsi and probe-scsi-all. 
X
XSCSI Notes: 
X
XThe negotiated maxiumum synchronous transfer rate normally will be the
Xlesser of the maximum rate supported by the adapter and the maximum rate
Xsupported by the device, but it can be lower than this under various
Xcircumstances.  This rate is typically negotiated at reboot (SunOS 4.1 and
X4.1.1 report it for each synchronous device), but it can also be
Xrenegotiated during operations if necessary.
X
XSCSIINFO notes:
X        - tested on SunOS 4.1.1 through 4.1.3, SunOS 5.2 and 5.3. 
X        - "-s" option most useful for SunOS 4.1.2 and above, since in
X          these versions of the OS, the SCSI driver no longer reports the
X          transfer rates it negotiates with synchronous SCSI devices on boot.
X        - Does nothing on suns without ESP host adapters or without openboot 
X          prom support. 
X        - Supports multiple ESP host adapters
X        - Scsiinfo needs to be recompiled on any (even minor) OS releases that
X          changed the format of the esp structure. For example, a 4.1.1
X          binary will not work on 4.1.2 or 4.1.3.
X        - Scsiinfo can only probe a SCSI device when the following conditions
X          are met:
X                - the device's device-driver supports user-mode SCSI commands.  
X                - scsiinfo can find the device's character special file. 
X                - the character special file is readable. 
X                - nothing has an exclusive open on the character special file. 
X          Sun's 4.x tape driver doesn't support user-mode SCSI commands. Sun's
X          disk drivers do. Sun's CD-ROM driver only does when there is
X          valid media in the drive. In Solaris 2.2 or greater, /usr/sbin/vold,
X          if it is running, may hold an exclusive open on the CD-ROM device, 
X          preventing a probe from succeeding. If scsiinfo cannot probe a drive,
X          it returns a message saying why the probe failed. 
X	- The format.dat entries generated by SCSIINFO are certainly not
X	  perfect. Firstly, SCSIINFO just guesses at the bpt figure (bpt =
X          bits per track), because there's no standard way of querying the
X          drive for this figure. Secondly, some drives are overly optimistic
X          in their estimation of the number of blocks available; if a 
X          format.dat entry runs into problems, try reducing ncyl until it
X          works. Finally, some drives simply don't return a valid rpm figure;
X          if this is the case, SCSIINFO will report an error and make a
X          guess of 3600rpm, which may not be correct. 
X
XInstallation:
X        1. Edit the Makefile to taste. 
X        2. Compile. 
X        3. scsiinfo needs to be able to read /dev/kmem. For use by users
X           without read permissions on /dev/kmem, it can be made setgid 
X           kmem or setgid sys. "make install" will install it setgid kmem.
X        4. If SCSI probing (scsiinfo -p) or drive format querying (scsiinfo
X           -f or -F) is to work for a given device, scsiinfo will need to 
X           be able to access the device via a raw/character device file in 
X           /dev (or /devices/... in Solaris 2.x).  
X	5. When probing for disks, scsiinfo attempts to access the raw 
X           device for the third ("c") partition. This device file must be 
X           readable to root! If users other than root are to use SCSI probing, 
X           scsiinfo can be installed setuid root (or setgroupid or setuid to 
X           a group or user that can read the devices, like "operator").
X
XPorting notes:
X          - It will be almost impossible to port to 4.0.x without source, since
X            there are no suitable include files. 
X          - The esp driver has tended to change quite a bit between releases;
X            the code is written to be as portable as possible, but future
X            (greater than 5.3) versions of SunOS 5.x may break something. 
X
XBug reports, fixes, enhancements, etc. are welcome.
X
XJohn 
X--
XJohn DiMarco                                              jdd@cdf.toronto.edu
XComputing Disciplines Facility Systems Manager            jdd@cdf.utoronto.ca
XUniversity of Toronto                                     EA201B,(416)978-1928
END_OF_FILE
if test 5155 -ne `wc -c <'README'`; then
    echo shar: \"'README'\" unpacked with wrong size!
fi
# end of 'README'
fi
if test -f 'patchlevel.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'patchlevel.h'\"
else
echo shar: Extracting \"'patchlevel.h'\" \(125 characters\)
sed "s/^X//" >'patchlevel.h' <<'END_OF_FILE'
X#ifndef lint
Xstatic char patchlevel[] = "scsiinfo Version 3.3 $Id: patchlevel.h,v 3.3 1994/08/02 22:18:52 jdd Exp $";
X#endif
END_OF_FILE
if test 125 -ne `wc -c <'patchlevel.h'`; then
    echo shar: \"'patchlevel.h'\" unpacked with wrong size!
fi
# end of 'patchlevel.h'
fi
if test -f 'Makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'Makefile'\"
else
echo shar: Extracting \"'Makefile'\" \(1881 characters\)
sed "s/^X//" >'Makefile' <<'END_OF_FILE'
XCC = cc # or gcc, if you prefer
XINCLUDEDIRS = -I.
X
X#
X# Remove -lelf for SunOS 4.x
X#
XLIBRARIES = -lkvm -lelf
X
X#
X# Hard-code SUNOS_VERSION if you're using a non-sun make (eg. gnu make). For 
X# example, SUNOS_VERSION = 4.1.3
X#
XSUNOS_VERSION:sh = /usr/bin/uname -r
X
X#
X# DRVR_SPECIFIC_WKAROUNDS adds some smarts to scsiinfo to recognize
X# the presence of certain 3rd party drivers requiring special handling. 
X# Leave this in unless you experience problems.
X#
XDEFS = -DDRVR_SPECIFIC_WKAROUNDS -DSUNOS_VERSION=\"$(SUNOS_VERSION)\" 
X
XCFLAGS = $(DEFS) -g $(INCLUDEDIRS)
XLDFLAGS = 
XLINTFLAGS = $(DEFS) -ha $(INCLUDEDIRS) 
XSRCS = scsiinfo.c utils.c uscsi.c format.c
XOBJS = $(SRCS:.c=.o)
XRM = /bin/rm -rf
X
X#
X# Use /usr/bin/install for SunOS 4.x
X#
XINSTALL = /usr/ucb/install 
X
XETCDIR = /local/etc
XMANDIR = /local/man/man1
X
X#
X# Set MODE to 4755, if you want this to run setuid root. 
X# -p/-f/-F may not work otherwise. By default, scsiinfo is set to run setgid
X# sys (or kmem for SunOS 4.x), which allows only root to use -p/-f/-F, but 
X# everything else to work for other users. 
X#
XMODE = 2755
XOWNER = root 
XGROUP = sys # kmem for SunOS 4.x
X
X#
X# End of user-configurable options
X#
X
Xall:: scsiinfo
X
Xscsiinfo: $(OBJS) 
X	$(RM) $@
X	$(CC) $(LDFLAGS) -o $@ $(OBJS) $(LIBRARIES)
Xlint:
X	lint $(LINTFLAGS) $(SRCS)
Xlintport:
X	lint -p $(LINTFLAGS) $(SRCS)
Xclean:
X	rm -f $(OBJS) scsiinfo
Xdepend:
X	makedepend -- $(CFLAGS) -- $(SRCS)
X
Xinstall: scsiinfo
X	$(INSTALL) -m $(MODE) -o $(OWNER) -g $(GROUP) scsiinfo $(ETCDIR) 
X
Xinstall.man: scsiinfo.1
X	$(INSTALL) -m 644 scsiinfo.1 $(MANDIR)
X
Xshar:
X	shar COPYRIGHT MANIFEST README patchlevel.h Makefile scsiinfo.1 \
X	scsiinfo.c utils.c utils.h uscsi.h uscsi.c \
X	sunos4.h sunos5.h sundev sundev/dmaga.h \
X	format.c format.h >scsiinfo.shar
X
X# DO NOT DELETE THIS LINE -- make depend depends on it.
Xscsiinfo.o:	patchlevel.h sunos4.h sunos5.h utils.h uscsi.h format.h
END_OF_FILE
if test 1881 -ne `wc -c <'Makefile'`; then
    echo shar: \"'Makefile'\" unpacked with wrong size!
fi
# end of 'Makefile'
fi
if test -f 'scsiinfo.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'scsiinfo.1'\"
else
echo shar: Extracting \"'scsiinfo.1'\" \(5083 characters\)
sed "s/^X//" >'scsiinfo.1' <<'END_OF_FILE'
X.TH scsiinfo 1 "Nov 12, 1993"
X.SH scsiinfo
Xscsiinfo \- obtain information about scsi devices attached to a Sun system 
X.SH SYNOPSIS
X.B scsiinfo
X[
X.B \-f\ raw_disk_device
X]
X[
X.B \-F\ raw_disk_device
X]
X[
X.B \-V
X]
X[
X.B \-c
X]
X[
X.B \-s
X]
X[
X.B \-p
X]
X[
X.B \-q
X]
X[
X.B \-o
X]
X.SH DESCRIPTION
X.B scsiinfo
Xdisplays information about SCSI devices attached to a given system, as seen
Xby the Sun ESP device driver. For each target known to the SCSI host adapter,
X.B scsinfo
Xreports whether it is synchronous or asynchronous, whether or not the
Xtranfers to/from the target are clean or susceptible to noise, and whether
Xor not the target can disconnect and reconnect. When a target supports
Xsynchronous transfer, the negotiated maximum transfer rate (in MB/sec) is
Xreported. Furthermore, 
X.B scsiinfo
Xcan query SCSI devices for vendor, product, and revision information. Finally,
X.B scsiinfo
Xcan query a SCSI disk for format and geometry information, and 
Xgenerate a suitable format.dat entry for it.
X.SH OPTIONS
X.IP \fB\-c\fP
XIn addition, provide type and speed (clock rate) information about the ESP 
Xcontrollers on the machine. 
X.IP \fB\-V\fP
XPrint out 
X.B scsiinfo
Xversion information and exit.
X.IP \fB\-s\fP
XReport "Target now Synchronous" messages for all synchronous devices in
Xthe style of the SunOS 4.1 and 4.1.1 kernels at bootup. 
X.IP \fB\-p\fP
XProbe SCSI devices, report their type, whether or not they are removable or
Xnon-removable, and report the device's vendor, product, and revision data.
XThis option provides much the same information as the Openboot prom's 
X"probe-scsi-all" command. This option may require special privileges, depending
Xon how 
X.B scsiinfo
Xis installed, and may not work for all devices.
X.IP \fB\-q\fP
XQuiet mode. Do not display transfer information for the specified devices.
XUseful in shell scripts when only the return status is desired. 
X.IP \fB\-f\ raw_disk_device\ \fP
XReport disk format and geometry information. The raw disk device to be queried
X(eg /dev/rsd0c or /dev/rdsk/c0t0d0s2) must be specified.
X.IP \fB\-F\ raw_disk_device\ \fP
XQuery the specified raw disk device for format and geometry information, and 
Xconstruct a format.dat entry for it. 
X.IP \fB\-o\fP
XWhen querying a drive for format settings (using \fB\-f\fP or \fB\-F\fP), 
Xreport the original manufacturer's defined settings, instead of the settings
Xcurrently in effect. This is useful if the drive is not formatted correctly
Xor at all. 
X.SH SEE ALSO
XSunOS 4.x: devinfo(8S), SunOS 5.x: prtconf(1M)
X.SH DIAGNOSTICS
XThe return status of 
X.B scsiinfo
Xindicates the number of devices detected whose connections have been determined
Xby the kernel to be noisy. 
X.B scsiinfo
Xreturns -1 (255) if unable to read the kernel or if run on an unsupported
Xarchitecture. 
X.SH HISTORY
XWritten by John DiMarco (jdd@cdf.toronto.edu) at the University of Toronto
X.SH LIMITATIONS
XOnly machines with Sun ESP SCSI host adapters and Openboot proms are supported. 
XThese include sun4c, sun4d, and sun4m machines. 
X.PP
XSCSI devices that do not have loaded drivers or which have drivers that
Xdo not support Sun's user SCSI interface, cannot be probed by scsiinfo -p.
XIn particular, CD-ROM devices using the Sun 4.x driver apparently cannot be 
Xprobed unless a CD is loaded. Furthermore, if some process is exclusively
Xholding open a device, 
X.B scsiinfo
Xwill not be able to probe it. This is often the case with the CD-ROM under 
XSolaris 2.x, when the Volume Manager is running.
X.PP
XSince the user-mode SCSI interface requires read access to a raw character 
Xdevice, probing and format/geometry querying will only work if the user running 
X.B scsiinfo
Xcan read the appropriate device file, or if 
X.B scsiinfo
Xis installed setgid or setuid to a group or user that has the appropriate
Xprivileges. If
X.B scsiinfo 
Xcannot probe a device, it will report the reason.
X.PP
XOptions other than
X.B -o
Xhave no effect when 
X.B -f
Xor 
X.B -F 
Xis specified. 
X.B -o
Xhas no effect if
X.B -f
Xor
X.B -F 
Xis not specified.
X.PP
XWhen generating a format.dat entry, 
X.B scsiinfo
Xjust makes an educated guess for the bpt (bits per track) figure, since it 
Xisn't possible to query the drive for this.
X.PP
XWhen queried for format and geometry information, some disks drives report 
Xincorrect values for rpm (rotations per minute).
X.B scsiinfo
Xwill use 3600 if the reported value is obviously wrong. Furthermore,
Xsome disk drives are overly optimistic when reporting physical capacity,
Xwhich causes 
X.B scsiinfo
Xto generate an format.dat entry for the drive that causes format to report
Xerrors when labelling. If this occurs, decrease the value of ncyl until
Xthe problem goes away.
X.PP 
XUnder Solaris 2.x, if a Central Data SCSITerminal Server is attached to a
Xparticular SCSI controller, device transfer rates and noise information will 
Xbe unavailable for any device on that controller. The Central Data driver 
Xappears to clobber the data structures that 
X.B scsiinfo
Xobtains this information from.
X.PP
XAs far as 
X.B scsiinfo
Xis concerned, 1 MB = 1000 KB, and 1GB = 1000000 KB. This is the industry 
Xconvention for reporting disk sizes. 
END_OF_FILE
if test 5083 -ne `wc -c <'scsiinfo.1'`; then
    echo shar: \"'scsiinfo.1'\" unpacked with wrong size!
fi
# end of 'scsiinfo.1'
fi
if test -f 'scsiinfo.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'scsiinfo.c'\"
else
echo shar: Extracting \"'scsiinfo.c'\" \(11382 characters\)
sed "s/^X//" >'scsiinfo.c' <<'END_OF_FILE'
X/*
X * scsiinfo.c  -  determine SCSI info. 
X *                Only ESP SCSI host adapters are supported.
X *
X * Author: John DiMarco, University of Toronto, CDF
X *         jdd@cdf.toronto.edu
X */
X
X#ifndef lint
Xstatic char rcsid[] = "$Header: /u/jdd/src/jdd/scsiinfo/RCS/scsiinfo.c,v 3.4 1994/07/22 19:47:39 jdd Exp $";
X#endif
X
X/* 
X * $Log: scsiinfo.c,v $
X * Revision 3.4  1994/07/22  19:47:39  jdd
X * -V option supported, get_scsiaddr needs dname, esp_p and esp_softc
X * (erased in an earlier release) is needed by 4.1.1 code
X *
X * Revision 3.3  1994/07/18  17:08:09  jdd
X * special case for Central Data STS added, minor cleanup
X *
X * Revision 3.2  1994/02/14  19:36:43  jdd
X * EIO means media not loaded, not driver doesn't support uscsi
X *
X * Revision 3.1  1994/01/11  16:06:14  jdd
X * added -o option, minor cleanup.
X *
X * Revision 3.0  1993/12/21  20:59:29  jdd
X * updates for format stuff
X *
X * Revision 3.0  1993/12/21  20:59:29  jdd
X * updates for format stuff
X *
X * Revision 1.6  1993/12/02  01:18:48  jdd
X * report reason why probe failed
X *
X * Revision 1.5  1993/11/15  21:57:26  jdd
X * More informative error messages, check for unsupported architecture,
X * check for OS version mismatch
X *
X * Revision 1.4  1993/11/12  20:36:47  jdd
X * Only count noisy devices with lun=0
X *
X * Revision 1.3  1993/11/12  20:28:30  jdd
X * almost complete rewrite for 2.0
X * list devices via devinfo tree, rather than looping through all
X * scsi targets. Support for -p, -q options. Split OS dependent
X * stuff off into sunos4.h, sunos5.h, general cleanup
X *
X * Revision 1.2  1993/05/17  22:39:26  jdd
X * -v option is really -c.
X * Added patchlevel.h
X *
X * Revision 1.1  1993/05/17  17:03:13  jdd
X * Initial revision
X *
X *
X */
X
X#include "patchlevel.h"
X#include "uscsi.h"
X#include "format.h"
X#include <stdio.h>
X
X#ifdef FILENAME_MAX	/* defined in stdio.h only for SunOS >=5.x */
X#define SYSV
X#endif
X
X#include <sys/param.h>
X#include <values.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <nlist.h>
X#include <kvm.h>
X#include <fcntl.h>
X#include <sys/utsname.h>
X#include "utils.h"
X
X#define MAXESP 255	
X#define BUFFSIZE 80
X
Xstatic kvm_t *kd;
X#define getkvm(a,b,l) kvm_read(kd,a,(char *)b,l)
X
Xstatic char *kernel_getstring(address)
Xu_long address;
X{
X	static char buff[BUFFSIZE];
X
X	if(-1==getkvm(address, buff, sizeof(buff))){
X		Error("kernel_getstring");
X	}
X	buff[BUFFSIZE-1]='\0'; /* just in case it's not null-terminated */
X	return(buff);
X}
X	
X/* include OS-dependent stuff */
X#ifdef SYSV
X#include <sunos5.h>
X#else 
X#include <sunos4.h>
X#endif
X
Xstatic char *devicepath;
Xchar *progname;
Xint d;
X
Xstatic int controller=0; /* give controller information */
Xstatic int bootstyle=0;  /* Use SunOS4.x boot "...now Synchronous..." format */
Xstatic int probe=0;      /* Probe SCSI device if possible */
Xstatic int quiet=0;	 /* Quiet mode: don't report synch messages */
Xstatic int noisycount=0; /* number of noisy devices */
Xstatic int formatinfo=0; /* Report format info */
Xstatic int formatdat=0;  /* Generate format.dat */
Xstatic int original=0;   /* Use manuf's original settings for format info */
X
Xstatic void usage()
X{
X	fprintf(stderr, 
X  "Usage: %s [-V][-o][-c][-s][-p][-q][-f diskdevice][-F diskdevice]\n", 
X			progname);
X	exit(2);
X}
X
Xstatic char *espType(typecode)
Xunsigned int typecode;
X{
X	/* see /usr/include/[sys/]scsi/adapters/espreg.h */
X	switch(typecode){
X	case 0:		return("ESP100/NCR53C90");
X	case 1: 	return("ESP100A/NCR53C90A");
X	case 2:		return("ESP236");
X	case 3:		return("FAS100/100A");
X	case 4:		return("FAS236");
X	case 5:		return("FAST");
X	default:	return("unknown");
X	}
X}
X
Xstatic u_int get_speed(esp, i)
Xstruct esp *esp;
Xint i; /* target index */
X{
X	u_int cycletime, speed;
X
X	/*
X	 * Synch cycle time in milliseconds is the
X	 * number of ticks in the period multiplied
X	 * by the tick rate. e_clock_conv is the
X	 * esp's tick rate in units of 5MHz.
X	 */
X	cycletime = esp->e_clock_conv ? (esp->e_period[i] *
X			(1000/(int)(5*esp->e_clock_conv))) : 0;
X
X	/*
X	 * Compute speed in thousanths of MBs/sec.
X	 */
X	speed = cycletime?((((1000*1000*1000)/cycletime)+999)/1000):0;
X
X	return(speed);
X}
X
Xstatic void controller_message(cnum, esp)
Xint cnum;
Xstruct esp *esp;
X{
X	printf("esp%d:", cnum);
X	printf(" type %d (%s)", (u_int)esp->e_type,
X		espType(esp->e_type));
X	printf(" speed %dMHz", (u_int)esp->e_clock_conv*5);
X	printf("\n");
X}
X
Xstatic void boot_synch_message(espnum, i, speed)
Xint espnum;
Xint i; /* target index */
Xu_int speed;
X{
X	if(speed) printf(
X  "esp%d:\tTarget %d now Synchronous at %d.%d mb/s max transmit rate\n",
X			 espnum, i, speed/1000, speed%1000);
X}
X
Xstatic void synch_message(esp, i, speed)
Xstruct esp *esp;
Xint i;
Xu_int speed;
X{
X	if(esp->e_weak & ~(esp->e_targets)) {
X		/* don't believe esp synch info if e_weak mentions 
X		 * unprobed targets; something has gone awry. Some versions of 
X		 * the 5.x ct driver for the Central Data STS do this.
X		 */
X		printf("Unknown");
X	} else if(speed && (esp->e_sync_known & (1<<i))){
X		printf("Synchronous(%d.%dMB/sec)", speed/1000, speed%1000);
X	} else {
X		printf("Asynchronous");
X	}
X	if(esp->e_weak & ~(esp->e_targets)) {
X		/* again, don't believe e_weak if mentions unprobed targets */
X		printf(" Unknown");
X	} else if(esp->e_weak & (1<<i)){
X		printf(" Noisy");
X	} else {
X		printf(" Clean");
X	}
X	if(esp->e_nodisc & ~(esp->e_targets)) {
X		/* don't believe e_nodisc if it mentions unprobed targets */
X		printf(" Unknown");
X	} else if(esp->e_nodisc & (1<<i)){
X		printf(" CannotReconnect");
X	} else {
X		printf(" CanReconnect");
X	}
X}
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X	int c, j;
X	int errflg = 0;
X	extern char *optarg;
X	struct esp esp[1], *esp_p, *esp_softc;
X	u_long addr;
X	u_int nesp;
X	char *dname; 
X	struct utsname un;
X	char *diskdevice;
X
X	progname = argv[0];
X	while ((c = getopt(argc, argv, "Vodcspqf:F:")) != EOF)
X		switch (c) {
X		case 'V':
X			printf("%s\n", patchlevel);
X			exit(0);
X			break;
X		case 'd':
X			++d;
X			break;
X		case 'c': 
X			/* output controller information */
X			controller++;
X			break;
X		case 's':
X			/* Use SunOS4.x boot-style "now Synchronous" format */
X			bootstyle++;
X			break;
X		case 'p':
X			/* probe probe-able devices */
X			probe++;
X			break;
X		case 'q':
X			/* quiet mode */
X			quiet++;
X			break;
X		case 'f': 
X			/* output format info */
X			formatinfo++;
X			diskdevice=optarg;
X			break;
X		case 'F':
X			/* output format.dat */
X			formatinfo++;
X			formatdat++;
X			diskdevice=optarg;
X			break;
X		case 'o':
X			/* use manufacturer's original settings for fmt info */
X			original++;
X			break;
X		default:
X			/* parameter error */
X			errflg++;
X			break;
X		}
X	if (errflg) {
X		usage();
X	}
X
X	/* check OS version and machinetype, quit now if mismatch */
X	uname(&un);
X
X
X	if(formatinfo){
X		format(formatdat, un.release, diskdevice, original);
X		exit(0);
X	} 
X
X	if(!STREQ(SUNOS_VERSION, un.release)){
X		Error(
X"Version mismatch: compiled for SunOS %s, this is SunOS %s.",
X		      SUNOS_VERSION, un.release);
X	}
X	if((0!=strncmp(un.machine, "sun4", 4)) || strlen(un.machine)<(u_int)5){
X		Error( "%s kernel architecture not supported.", un.machine);
X	}
X
X        if(NULL==(kd=kvm_open(NULL, NULL, NULL, O_RDONLY, progname))){
X		Error("Cannot read kernel, giving up.");
X        }
X        if(0!=kvm_nlist(kd, nl)){
X                Error("Cannot read a required kernel symbol.");
X        }
X	if(-1==getkvm(nl[N_ESP_SOFTC].n_value, &addr, sizeof(addr))){
X		Error("kvm_read: esp_softc");
X	}
X
X	if((u_long)NULL==addr) exit(0); /* no esp's */
X
X        if(-1==getkvm(addr, esp, sizeof(struct esp))){
X		Error("kvm_read: initial esp");
X	}
X
X	esp_softc=esp_p=(struct esp *)addr;
X
X	nesp=get_nesp();
X	if(0==nesp) exit(0);
X
X	for(j=0;j<nesp;j++){
X		struct dev_info di, *next;
X		if(NULL==(char *)addr) break;
X                if(-1==getkvm(addr, esp, sizeof(struct esp))){
X			Error("kvm_read: #%d esp", j);
X		}
X
X		/* 
X		 * grab the devinfo structure for the esp controller. CNUM 
X		 * requires it, and we need it to determine the device names.
X		 */
X		if(-1==getkvm((u_long)esp->e_dev, &devi, sizeof(devi))){
X			Error("kvm_read: #%d esp devinfo", j);
X		} 
X
X		if(probe) devicepath = get_devicepath(j);
X
X		esp->e_dev=(dev_info_t)&devi; /* for CNUM */
X
X		if(controller) controller_message(CNUM, esp);
X
X		init_scsitarget();
X
X		/* 
X		 * Now, traverse esp's devinfo child list, looking for
X		 * attached drivers (i.e. DDI_CF2 is true). If we find
X		 * an attached driver, we presume it is an active device.
X		 */
X
X		for(next=ddi_get_child(&devi);
X		    NULL!=next; 
X		    next=ddi_get_next_sibling(&di)){
X			char *devicename, *addrname;
X			int target, lun;
X
X			if(-1==getkvm((u_long)next,
X				&di, sizeof(di))){
X			    Error("kvm_read: #%d esp devinfo child", j);
X			}
X
X			if(!DDI_CF2(&di)) continue; /* skip */
X
X			/*
X			 * Get the device name and address, and 
X			 * compute the device path for it
X			 */
X
X			/* get device name */
X			dname=s(kernel_getstring(
X				(u_long)ddi_get_name(&di)));
X			/* ... and address */
X			addrname=s(get_addr(&di));
X
X#ifdef CENTRAL_DATA_CT
X			if(STREQ("ct", dname)) {
X				/* special case for Central Data STS driver */
X				if(!di.devi_minor) continue;
X			} 
X#endif /* CENTRAL_DATA_CT */
X
X			if(probe) {
X				/* compute device name */
X				if(STREQ("sd", dname)){
X					/* disk device */
X					devicename = cat(
X						devicepath, "/", 
X						DEV_PREFIX, dname, 
X						DEV_INFIX, addrname, 
X						DISK_SUFFIX, NULL);
X#ifdef CENTRAL_DATA_CT
X#if notdef
X				} else if(STREQ("ct", dname)) {
X					char maj[2];
X					maj[0]=addrname[0];
X					maj[1]='\0';
X					lun=0;
X					devicename = cat(
X						devicepath, "/",
X						DEV_PREFIX,
X						dname, DEV_INFIX,
X						addrname,
X						DEV_SUFFIX, "stsd", 
X						maj, NULL);
X#endif /* notdef */
X#endif /* CENTRAL_DATA_CT */
X				} else {
X					devicename = cat(
X						devicepath, "/", 
X						DEV_PREFIX,
X						dname, DEV_INFIX, 
X						addrname, 
X						DEV_SUFFIX, NULL);
X				}
X			}
X
X			if(-1==get_scsiaddr(dname, &di, &target, &lun)){
X				Error("scsiaddr: #%d", j);
X			}
X
X			if(0==lun && (esp->e_weak & (1<<target))) noisycount++;
X
X			if(!quiet){
X				if(bootstyle) {
X					if(lun==0){
X						boot_synch_message(CNUM, 
X							target, 
X							get_speed(esp, target));
X					}
X				} else {
X					printf(
X					   "esp%d: %s%s tgt %d lun %d:\n\t", 
X						CNUM, dname, addrname, 
X						target, lun);
X					synch_message(esp, target, 
X						get_speed(esp, target));
X					printf("\n");
X				}
X			}
X			if(probe){
X				printf("\t");
X				if(-1==(scsi_probe(devicename, lun))){
X					switch(errno){
X					case EACCES:
X						printf(
X"<<< SCSI probe failed: no permission to access device special file >>>\n");
X						break;
X					case ENOTTY:
X						printf(
X"<<< SCSI probe failed: device driver doesn't support probing >>>\n");
X						break;
X					case ENXIO:
X					case EIO:
X						printf(
X"<<< SCSI probe failed: device not accessible (media not loaded?) >>>\n");
X						break;
X					case EBUSY:
X						printf(
X"<<< SCSI probe failed: device is busy >>>\n");
X						break;
X					case ENOENT:
X						printf(
X"<<< SCSI probe failed: device special file not available >>>\n");
X						break;
X					default:
X						perror("scsi probe failed");
X						printf("errno %d\n", errno);
X						break;
X					}
X				} else {
X					printf("\n");
X				}
X				free(devicename);
X			}
X			free(addrname);
X			free(dname);
X		}
X
X#ifdef OLD_SUNOS
X		/* SunOS 4.1.1 and previous, table */
X		addr=(u_long)(++esp_p);
X#else
X		/* SunOS 4.1.2 and later, linked list */
X                addr=(u_long)esp->e_next;
X#endif
X
X	}
X	return(noisycount);
X}
END_OF_FILE
if test 11382 -ne `wc -c <'scsiinfo.c'`; then
    echo shar: \"'scsiinfo.c'\" unpacked with wrong size!
fi
# end of 'scsiinfo.c'
fi
if test -f 'utils.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'utils.c'\"
else
echo shar: Extracting \"'utils.c'\" \(4163 characters\)
sed "s/^X//" >'utils.c' <<'END_OF_FILE'
X/*
X * utils.c: miscellaneous utilities
X *
X * Author: John DiMarco, University of Toronto, CDF
X *         jdd@cdf.toronto.edu
X */
X
X/* 
X * $Log: utils.c,v $
X * Revision 1.4  1994/07/22  18:45:01  jdd
X * stdlib.h is okay for sunos4
X *
X * Revision 1.3  1994/07/18  17:09:34  jdd
X * cleanup
X *
X * Revision 1.2  1993/11/12  20:30:59  jdd
X * cleanup, changed return status of Error
X *
X */
X
X#include <stdio.h>
X#include <stdlib.h>
X#ifdef FILENAME_MAX
X#include <string.h>
X#else
X#include <strings.h>
X#endif
X#include <varargs.h>
X#include "utils.h"
X
X#ifdef lint
X#undef va_arg
X#define va_arg(x,y) (y)NULL
X#endif
X
Xextern char *progname;
Xextern int d;
X
X/*
X * Error(): behaves like fprintf(stderr, ...) followed by exit(-1), except
X *          that the 'programname: ' preceeds the print, and a newline
X *	    follows it.
X */
X/*VARARGS*/
Xvoid Error(va_alist)
Xva_dcl
X{
X	va_list args;
X	char *format;
X
X	va_start(args);
X	format = va_arg(args, char *);
X	(void)fprintf(stderr, "%s: ", progname);
X	(void)vfprintf(stderr, format, args);
X	(void)fprintf(stderr, "\n");
X	va_end(args);
X	exit(-1);
X}
X
X/*
X * dfprintf(): behaves like fprintf, except the first argument must be a
X *            debugging level. The message will only be printed if "d"
X *            is equal to or greater than the debugging level.
X */
X/*VARARGS*/
Xvoid dfprintf(va_alist)
Xva_dcl
X{
X	va_list args;
X	int debugLevel;
X	FILE *stream;
X	char *format;
X	
X	va_start(args);
X	debugLevel = va_arg(args, int);
X	stream = va_arg(args, FILE *);
X	format = va_arg(args, char *);
X	if(d >= debugLevel){
X		(void)vfprintf(stream, format, args);
X	}
X	va_end(args);
X}
X	
X/*
X * Warning(): behaves like Error, except returns rather than exits.
X */
X/*VARARGS*/
Xvoid Warning(va_alist)
Xva_dcl
X{
X	va_list args;
X	char *format;
X
X	va_start(args);
X	format = va_arg(args, char *);
X    (void)fprintf(stderr, "%s: ", progname);
X    (void)vfprintf(stderr, format, args);
X    (void)fprintf(stderr, "\n");
X    va_end(args);
X}
X
XFILE *efopen(file, mode)
Xchar *file, *mode;
X{
X	FILE *fp;
X	if (NULL!=(fp=fopen(file,mode)))
X		return(fp);
X	Error("can't open file \"%s\" mode \"%s\"", file, mode);
X	/*NOTREACHED*/
X}
X
Xvoid efclose(f)
XFILE *f;
X{
X	if(EOF==fclose(f))
X		Error("can't close file");
X	/*NOTREACHED*/
X}
X
X/*
X * mylib_malloc(): Checks if it gets a NULL pointer, calls Error if so.
X */
Xchar *mylib_malloc(size, file, line)
Xunsigned size;
Xchar *file;
Xint line;
X{
X	char *result;
X
X	result = malloc(size);
X	if(NULL==result){
X		Error("Out of memory at line %d in \"%s\".", line, file);
X	}
X	return(result);
X}
X
X/*
X * mylib_realloc(): Checks if it gets a NULL pointer, calls Error if so.
X */
Xchar *mylib_realloc(ptr, size, file, line)
Xchar *ptr, *file;
Xunsigned size;
Xint line;
X{
X	char *result;
X
X	result = realloc(ptr, size);
X	if(NULL==result){
X		Error("Out of memory at line %d in \"%s\".", line, file);
X	}
X	return(result);
X}
X
X/*
X * mylib_scopy(): Takes a string and creates a new physical copy of it.
X */
Xchar *mylib_scopy(string, file, line)
Xchar *string, *file;
Xint line;
X{
X	char *result;
X
X	result = malloc((unsigned)strlen(string)+1);
X
X	if(NULL==result){
X		Error("Out of memory at line %d in \"%s\".", line, file);
X	}
X	(void)strcpy(result, string);
X	return(result);
X}
X
X/*
X * mylib_srcopy(): Reallocs first string to make room for second, copies it.
X */
Xchar *mylib_srcopy(s1, s2, file, line)
Xchar *s1, *s2, *file;
Xint line;
X{
X	s1=mylib_realloc(s1, (unsigned)strlen(s2)+1, file, line);
X	(void)strcpy(s1, s2);
X	return(s1);
X}
X
X/*
X * cat(): Take a list of strings, followed by NULL, return their concatenation
X *        in malloc'ed space.
X */
X/*VARARGS*/
Xchar *cat(va_alist)
Xva_dcl
X{
X	va_list args;
X	unsigned length=1;
X	char *str, *newstr;
X
X	/* get length */
X	va_start(args);
X	loop{
X		str = va_arg(args, char *);
X		if(NULL!=str){
X			 length+=strlen(str);
X		} else {
X			break;
X		}
X	}
X	va_end(args);
X
X	newstr=malloc(length);
X	if(NULL==newstr) Error("Out of memory in cat()");
X	
X	newstr[0]=(char)0;
X
X	/* create string */
X	va_start(args);
X	loop{
X		str = va_arg(args, char *);
X		if(NULL!=str) {
X			(void)strcat(newstr, str);
X		} else {
X			break;
X		}
X	}
X va_end(args);
X#ifdef lint
X	args=args; /* make lint shut up about "args set but not used" */
X#endif
X	return(newstr);
X}
END_OF_FILE
if test 4163 -ne `wc -c <'utils.c'`; then
    echo shar: \"'utils.c'\" unpacked with wrong size!
fi
# end of 'utils.c'
fi
if test -f 'utils.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'utils.h'\"
else
echo shar: Extracting \"'utils.h'\" \(1848 characters\)
sed "s/^X//" >'utils.h' <<'END_OF_FILE'
X/*
X * utils.h: header file for utils.c, various useful macros
X *
X * Author: John DiMarco, University of Toronto, CDF
X *         jdd@cdf.toronto.edu
X */
X
X/* 
X * $Log: utils.h,v $
X * Revision 1.2  1993/11/12  20:31:14  jdd
X * cleanup
X *
X */
X
X/* new - mallocs any sized type */
X#ifndef lint
X#define new(t) (t *)mylib_malloc(sizeof(t),__FILE__,__LINE__)
X#else
X#define new(t) (t *)NULL
X#endif
X
X/* mem - mallocs a given number of bytes */
X#define mem(l) mylib_malloc((unsigned)l,__FILE__,__LINE__)
X
X/* rmem - reallocs a given number of bytes */
X#define rmem(c,l) mylib_realloc(c,(unsigned)l,__FILE__,__LINE__)
X
X/* s - returns a copy of a given string */
X#define s(c) mylib_scopy(c,__FILE__,__LINE__)
X
X/* rs - returns a copy of the second string in place of the first string, 
X        using realloc */
X#define rs(c,d) mylib_srcopy(c,strlen(d),__FILE__,__LINE__)
X
X/* assert - error message if statement is false */
X#ifdef DEBUG
X#define assert(c) if(!(c))(void)fprintf(stderr,"%s: %d: Assert false\n",__FILE__,__LINE__)
X#else
X#define assert(c) 0
X#endif
X
X/* STREQ - indicate whether two strings are equal */
X#define STREQ(a, b) (*(a) == *(b) && strcmp((a), (b)) == 0)
X
X#define loop for(;;)
X#define NUL(x) (x)NULL
X#ifndef TRUE
X#define TRUE 1 
X#endif
X#ifndef FALSE
X#define FALSE 0 
X#endif
X#define YES 1
X#define NO 0
X
X/* Error - print like fprintf(stderr, ...) and die. Progname included at
X	   beginning of message, newline at end. */
Xextern void Error();
X/* Warning - like error, without dying */
Xextern void Warning();
X
Xextern char *mylib_malloc();   
Xextern char *mylib_realloc();
Xextern char *mylib_scopy();
Xextern char *mylib_srcopy();
Xextern char *cat();
Xextern char *getstr();
Xextern FILE *efopen();
Xextern void efclose();
Xextern void dfprintf();
X
Xextern char *progname; /* application's name. Used by Error, Warning. */
Xextern int d; /* debug level */
END_OF_FILE
if test 1848 -ne `wc -c <'utils.h'`; then
    echo shar: \"'utils.h'\" unpacked with wrong size!
fi
# end of 'utils.h'
fi
if test -f 'uscsi.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'uscsi.h'\"
else
echo shar: Extracting \"'uscsi.h'\" \(445 characters\)
sed "s/^X//" >'uscsi.h' <<'END_OF_FILE'
X/*
X * uscsi.h - header file for uscsi.c
X *
X * Author: John DiMarco, University of Toronto, CDF
X *         jdd@cdf.toronto.edu
X */
X
X/* 
X * $Log: uscsi.h,v $
X * Revision 3.0  1993/12/21  21:00:56  jdd
X * uscsi support for format querying
X *
X * Revision 1.1  1993/11/12  20:30:47  jdd
X * Initial revision
X *
X */
X
X/* Exported Procedures */
X
Xextern int scsi_probe();
Xextern int scsi_inquiry();
Xextern int scsi_modeinfo();
Xextern int scsi_capacity();
END_OF_FILE
if test 445 -ne `wc -c <'uscsi.h'`; then
    echo shar: \"'uscsi.h'\" unpacked with wrong size!
fi
# end of 'uscsi.h'
fi
if test -f 'uscsi.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'uscsi.c'\"
else
echo shar: Extracting \"'uscsi.c'\" \(6268 characters\)
sed "s/^X//" >'uscsi.c' <<'END_OF_FILE'
X/*
X * uscsi.c - User SCSI routines for querying devices.
X *
X * Author: John DiMarco,
X *         University of Toronto, Computing Disciplines Facility
X *         jdd@cdf.toronto.edu
X */
X
X#ifndef lint
Xstatic char rcsid[] = "$Header: /u/jdd/src/jdd/scsiinfo/RCS/uscsi.c,v 3.5 1994/07/18 17:06:28 jdd Exp $";
X#endif
X
X/* 
X * $Log: uscsi.c,v $
X * Revision 3.5  1994/07/18  17:06:28  jdd
X * off-by-one error in capacity
X *
X * Revision 3.4  1994/07/18  17:05:58  jdd
X * cleanup
X *
X * Revision 3.3  1994/02/14  19:37:10  jdd
X * atrks is alt_tracks_vol, not alt_tracks_zone
X *
X * Revision 3.2  1994/01/11  16:06:52  jdd
X * added support for -o (original) option
X *
X * Revision 3.1  1994/01/06  20:24:18  jdd
X * open with O_NDELAY otherwise open fails if no disk label.
X *
X * Revision 3.0  1993/12/21  21:00:39  jdd
X * uscsi support for format querying
X *
X * Revision 1.1  1993/11/12  20:30:33  jdd
X * Initial revision
X *
X * Revision 1.1  1993/11/12  20:30:33  jdd
X * Initial revision
X *
X *
X */
X
X#include <stdio.h>
X#ifdef FILENAME_MAX     /* defined in stdio.h only in SYSV systems */
X#define SYSV
X#include <string.h>
X#else
X#include <strings.h>
X#endif
X
X#include <sys/param.h>
X#include <values.h>
X#include <sys/types.h>
X#include <unistd.h>
X#include <fcntl.h>
X#include "utils.h"
X
Xextern int d;
X
X#ifdef SYSV
X
X#include <stdlib.h>
X#include <sys/scsi/generic/mode.h>
X#include <sys/scsi/generic/commands.h>
X#include <sys/scsi/impl/types.h>
X#include <sys/scsi/impl/uscsi.h>
X#include <sys/systeminfo.h>
X#define gethostname(b, l) sysinfo(SI_HOSTNAME, b, (long)l)
X#define bzero(b,l) memset(b,0,l)
X
X#else /* SYSV */
X
X#include <scsi/impl/types.h>
X#include <scsi/impl/uscsi.h>
X
X#endif /* SYSV */
X
X#define SCSIBUFLEN 8000
X
Xstatic char *scsi_dtype(dtype)
Xu_char dtype;
X{
X	switch(dtype){
X	case DTYPE_DIRECT: 	return("Disk");
X	case DTYPE_SEQUENTIAL: 	return("Tape");
X	case DTYPE_PRINTER: 	return("Printer");
X	case DTYPE_PROCESSOR: 	return("Processor");
X	case DTYPE_WORM:	return("WORM");
X	case DTYPE_RODIRECT:	return("Disk(RO)");
X	case DTYPE_SCANNER:	return("Scanner");
X	case DTYPE_OPTICAL:	return("Optical");
X	case DTYPE_CHANGER:	return("Changer");
X	case DTYPE_COMM:	return("Comm");
X	default:		return("Unknown");
X	}
X}
X
Xint scsi_probe(devname, lun)
Xchar *devname;
Xint lun;
X{
X	int dfd;
X	struct uscsi_cmd cmd;
X	union scsi_cdb cdb;
X	struct scsi_inquiry *inq;
X	char buff[SCSIBUFLEN]; 
X
X	if(-1==(dfd=open(devname, O_RDONLY|O_NDELAY))) return(-1);
X
X	inq = (struct scsi_inquiry *)buff;
X	
X	/* set up SCSI inquiry command */
X	bzero(&cdb, sizeof(cdb));
X	bzero(inq, sizeof(inq));
X	cdb.scc_cmd = SCMD_INQUIRY;
X	cdb.scc_lun = lun;
X 	cdb.g0_count0 = 200;
X	cmd.uscsi_cdb=(caddr_t)&cdb;
X	cmd.uscsi_cdblen=6; /* SCSI Group 0 cmd */
X	cmd.uscsi_bufaddr=(caddr_t)inq;
X	cmd.uscsi_buflen=SCSIBUFLEN;
X	cmd.uscsi_flags=USCSI_DIAGNOSE|USCSI_ISOLATE|USCSI_READ;
X
X	if(-1==ioctl(dfd, USCSICMD, &cmd)) return(-1);
X
X	printf("%s ", inq->inq_rmb?"Removable":"Non-removable");
X	printf("%s:\t", scsi_dtype(inq->inq_dtype));
X	printf("%-8.8s %-16.16s %-4.4s", inq->inq_vid, inq->inq_pid, 
X		inq->inq_revision);
X	return(0);
X}
X
Xint scsi_inquiry(fd, devicetype, vendor, product)
Xint fd, *devicetype;
Xchar *vendor, *product;
X{
X        struct uscsi_cmd cmd;
X        union scsi_cdb cdb;
X        struct scsi_inquiry *inq;
X        char buff[SCSIBUFLEN];
X
X        inq = (struct scsi_inquiry *)buff;
X
X        /* set up SCSI inquiry command */
X        bzero(&cdb, sizeof(cdb));
X        bzero(inq, sizeof(inq));
X        cdb.scc_cmd = SCMD_INQUIRY;
X        cdb.g0_count0 = 200;
X        cmd.uscsi_cdb=(caddr_t)&cdb;
X        cmd.uscsi_cdblen=6; /* SCSI Group 0 cmd */
X        cmd.uscsi_bufaddr=(caddr_t)inq;
X        cmd.uscsi_buflen=SCSIBUFLEN;
X        cmd.uscsi_flags=USCSI_DIAGNOSE|USCSI_ISOLATE|USCSI_READ;
X
X        if(-1==ioctl(fd, USCSICMD, &cmd)) return(-1);
X
X	*devicetype=inq->inq_dtype;
X	strncpy(vendor, inq->inq_vid, 8);
X	strncpy(product, inq->inq_pid, 16);
X	return(0);
X}
X
Xint scsi_capacity(fd, capacity)
Xint fd, *capacity;
X{
X        struct uscsi_cmd cmd;
X        union scsi_cdb cdb;
X        struct scsi_read_capacity {
X		int sectors;
X		int sector_size;
X		char junk[2];
X	} *inq;
X        char buff[SCSIBUFLEN];
X
X        inq = (struct scsi_read_capacity *)buff;
X
X        /* set up SCSI read_capacity command */
X        bzero(&cdb, sizeof(cdb));
X        bzero(inq, sizeof(inq));
X        cdb.scc_cmd = SCMD_READ_CAPACITY;
X        cmd.uscsi_cdb=(caddr_t)&cdb;
X        cmd.uscsi_cdblen=10;  /* SCSI Group 1 cmd */
X        cmd.uscsi_bufaddr=(caddr_t)inq;
X        cmd.uscsi_buflen=SCSIBUFLEN;
X        cmd.uscsi_flags=USCSI_READ;
X
X        if(-1==ioctl(fd, USCSICMD, &cmd)) return(-1);
X
X	*capacity=1+inq->sectors;
X	return(0);
X}
X
Xint scsi_modeinfo(fd, original, nsect, sector_size, pcyl, nhead, rpm, 
X			trks_zone, asect, atrks)
Xint fd, *nsect, *sector_size, *pcyl, *nhead, *rpm, *trks_zone, *asect, *atrks;
X{
X        struct uscsi_cmd cmd;
X        union scsi_cdb cdb;
X        struct mode_format mfmt;
X	struct mode_geometry mgeom;
X        char buff[SCSIBUFLEN];
X	struct mode_page page;
X	char *buffp;
X
X	/* set up SCSI page3 read */
X        bzero(&cdb, sizeof(cdb));
X        bzero(&mfmt, sizeof(mfmt));
X	cdb.scc_cmd = SCMD_MODE_SENSE;
X	cdb.g0_addr1 = MODEPAGE_ALLPAGES | (0x80 * original);
X	cdb.g0_count0 = 255;
X	cmd.uscsi_cdb=(caddr_t)&cdb;
X	cmd.uscsi_cdblen=6; /* SCSI Group 0 cmd */
X	cmd.uscsi_bufaddr=(caddr_t)buff;
X	cmd.uscsi_buflen=SCSIBUFLEN;
X	cmd.uscsi_flags=USCSI_DIAGNOSE|USCSI_ISOLATE|USCSI_READ;
X	
X        if(-1==ioctl(fd, USCSICMD, &cmd)) return(-1);
X
X	/* page one */
X	buffp = MODE_PAGE_ADDR((struct mode_header *)buff, char);
X	memcpy((char *)&page, buffp, sizeof(page));
X
X	/* page two */
X	buffp += sizeof(page) + (int)page.length;
X	memcpy((char *)&page, buffp, sizeof(page));
X
X	/* page three */
X	buffp += sizeof(page) + (int)page.length;
X	memcpy((char *)&mfmt, buffp, sizeof(mfmt));
X	
X	*trks_zone = (int)mfmt.tracks_per_zone;
X	*asect = (int)mfmt.alt_sect_zone;
X	*nsect = (int)mfmt.sect_track;
X	*atrks = (int)mfmt.alt_tracks_vol;
X	*sector_size = (int)mfmt.data_bytes_sect;
X
X	/* page four */
X	buffp += sizeof(page) + (int)mfmt.mode_page.length;
X	memcpy((char *)&mgeom, buffp, sizeof(mgeom));
X
X	*pcyl = (int)(mgeom.cyl_ub<<16) + (int)(mgeom.cyl_mb<<8) + 
X		(int)mgeom.cyl_lb;
X	*nhead = (int)mgeom.heads;
X	*rpm = (int)mgeom.rpm;
X
X	return(0);
X}
END_OF_FILE
if test 6268 -ne `wc -c <'uscsi.c'`; then
    echo shar: \"'uscsi.c'\" unpacked with wrong size!
fi
# end of 'uscsi.c'
fi
if test -f 'sunos4.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'sunos4.h'\"
else
echo shar: Extracting \"'sunos4.h'\" \(3533 characters\)
sed "s/^X//" >'sunos4.h' <<'END_OF_FILE'
X/*
X * sunos4.h: SunOS 4.1.x dependent code. 
X *
X * Author: John DiMarco, University of Toronto, CDF
X *         jdd@cdf.toronto.edu
X */
X
X/* 
X * $Log: sunos4.h,v $
X * Revision 1.3  1994/08/04  16:04:40  jdd
X * oops, get_addr returned pointer to non-static storage
X *
X * Revision 1.3  1994/08/04  16:04:40  jdd
X * oops, get_addr returned pointer to non-static storage
X *
X * Revision 1.3  1994/08/04  16:02:06  jdd
X * root@atom.city.ac.uk (David) pointed out that I was returning a pointer
X * to non-static storage.
X *
X * Revision 1.2  1994/07/22  19:46:24  jdd
X * cleanup
X *
X * Revision 1.1  1993/11/12  20:30:11  jdd
X * Initial revision
X *
X */
X
X#define _mon_openprom_h /* SunOS 4.1.2 silliness */
X
X#ifdef SUNOS4_1_0
X/* no espvar.h in SunOS 4.1 */
X#include <scsi/adapters/espreg.h>
X#else
X#include <scsi/adapters/espvar.h>
X#endif
Xstruct nlist nl[]={
X#define N_NESP 0
X        { "_nesp" },
X#define N_ESP_SOFTC 1
X        { "_esp_softc" },
X#define N_SCSI_CONF 2
X	{ "_scsi_conf" },
X        { "" },
X};
X
X#ifndef NPHASE
X#define OLD_SUNOS /* SunOS 4.1.1 or earlier */
X#undef CNUM
X#define CNUM (esp_p-esp_softc)
X#endif
X
X#include <sun/openprom.h>
X#define ddi_get_unit(a) ((struct dev_info *)a)->devi_unit
X#define ddi_get_name(a) ((struct dev_info *)a)->devi_name
X#define ddi_get_child(a) ((struct dev_info *)a)->devi_slaves
X#define ddi_get_parent(a) ((struct dev_info *)a)->devi_parent
X#define ddi_get_next_sibling(a) ((struct dev_info *)a)->devi_next
X#define DDI_CF2(a) (NULL != ((struct dev_info *)a)->devi_driver)
Xtypedef struct dev_info *dev_info_t;
X
X
X/*
X * device name is DEV_PREFIX<device>DEV_INFIX<addr>DEV_SUFFIX,
X * disk device name is DEV_PREFIX<device>DEV_INFIX<addr>DISK_SUFFIX,
X * 
X * For SunOS4: r<device><addr> or r<device><addr>c for disk
X */
X#define DEV_PREFIX "r"
X#define DEV_INFIX ""
X#define DEV_SUFFIX ""
X#define DISK_SUFFIX "c"
X
Xstatic struct dev_info devi;
Xstatic struct target_lookup {
X	struct scsi_conf *sc;
X	struct target_lookup *next;
X} *sctable = NUL(struct target_lookup *);
X
X/* Get number of ESP controllers */
Xstatic u_int get_nesp(){
X	u_int  nesp;
X        if(-1==getkvm(nl[N_NESP].n_value, &nesp, sizeof(nesp))) {
X                Error("kvm_read: nesp");
X        }
X	return(nesp);
X}
X
X/* Get path to specified esp device. Returned string is malloc'ed */
Xstatic char *get_devicepath(j)
Xint j;
X{
X	return(s("/dev"));
X}
X
X/* Get address of specified device. Note: returned in static storage */
Xstatic char *get_addr(di)
Xstruct dev_info *di;
X{
X	static char buff[20];
X	sprintf(buff, "%d", ddi_get_unit(di));
X	return(buff);
X}
X
Xstatic void init_scsitarget(){
X	/* Grab scsi_conf table */
X	int i=0;
X	struct scsi_conf *sctmp; 
X	struct target_lookup *tltmp;
X	u_long tableaddr;
X
X	tableaddr=(u_long)nl[N_SCSI_CONF].n_value;
X	loop{
X		sctmp=new(struct scsi_conf);
X		if(-1==getkvm(tableaddr, sctmp, sizeof(struct scsi_conf))){
X			Error("getkvm: scsi_conf\n");
X		}
X		if(NULL==sctmp->tname) {
X			free(sctmp);
X			break;
X		}
X		sctmp->tname = s(kernel_getstring(sctmp->tname));
X		sctmp->hname = s(kernel_getstring(sctmp->hname));
X
X		tltmp = new(struct target_lookup);
X		tltmp->next = sctable;
X		tltmp->sc = sctmp;
X		sctable=tltmp;
X
X		tableaddr += sizeof(struct scsi_conf);
X	}
X}
X
Xstatic int get_scsiaddr(name, di, target, lun)
Xchar *name;
Xstruct dev_info *di;
Xint *target, *lun;
X{
X	int unit;
X	struct target_lookup *i;
X
X	unit=ddi_get_unit(di);
X	for(i=sctable; NULL!=i; i=i->next){
X		if((unit==(int)i->sc->dunit) &&
X		   STREQ(name, i->sc->tname)){
X			*target = (int)i->sc->target;
X			*lun = (int)i->sc->lun;
X			return(0);
X		}
X	}
X	return(-1);
X}
END_OF_FILE
if test 3533 -ne `wc -c <'sunos4.h'`; then
    echo shar: \"'sunos4.h'\" unpacked with wrong size!
fi
# end of 'sunos4.h'
fi
if test -f 'sunos5.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'sunos5.h'\"
else
echo shar: Extracting \"'sunos5.h'\" \(4060 characters\)
sed "s/^X//" >'sunos5.h' <<'END_OF_FILE'
X/*
X * sunos5.h: SunOS 5.x dependent code. 
X *
X * Author: John DiMarco, University of Toronto, CDF
X *         jdd@cdf.toronto.edu
X */
X
X/* 
X * $Log: sunos5.h,v $
X * Revision 1.4  1994/07/22  19:46:34  jdd
X * need name argument for get_scsiaddr, since sunos4 code does.
X *
X * Revision 1.3  1994/07/18  17:08:44  jdd
X * special case for Central Data added, cleanup
X *
X * Revision 1.2  1993/12/02  01:19:16  jdd
X * need errno.h
X *
X * Revision 1.1  1993/11/12  20:30:23  jdd
X * Initial revision
X *
X */
X
X#ifdef DRVR_SPECIFIC_WKAROUNDS
X#ifndef CENTRAL_DATA_CT
X#define CENTRAL_DATA_CT
X#endif /* ndef CENTRAL_DATA_CT */
X#endif /* DRVR_SPECIFIC_WKAROUNDS */
X
X#include <stdlib.h>
X#include <unistd.h>
X#include <string.h>
X#include <errno.h>
X#include <sys/ddi.h>
X#include <sys/sunddi.h>
X#include <sys/ddi_impldefs.h>
X#include <sys/scsi/conf/device.h>
X#include <sys/scsi/impl/transport.h>
X#include <sys/scsi/adapters/espvar.h>
Xstatic struct nlist nl[]={
X#define N_ESP_SOFTC 0
X        { "esp_softc" },
X        { "" },
X};
X
X#define ddi_get_instance(a) ((struct dev_info *)a)->devi_instance /* for CNUM */
X#define ddi_get_name(a) ((struct dev_info *)a)->devi_name
X#define ddi_get_addr(a) ((struct dev_info *)a)->devi_addr
X#define ddi_get_child(a) ((struct dev_info *)a)->devi_child
X#define ddi_get_parent(a) ((struct dev_info *)a)->devi_parent
X#define ddi_get_next_sibling(a) ((struct dev_info *)a)->devi_sibling
X#define ddi_get_driver_private(a) ((struct dev_info *)a)->devi_driver_data
X
X/*
X * device name is DEV_PREFIX<device>DEV_INFIX<addr>DEV_SUFFIX,
X * disk device name is DEV_PREFIX<device>DEV_INFIX<addr>DISK_SUFFIX,
X * 
X * For SunOS5: <device>@<addr>: or <device>@<addr>:c,raw for disk
X */
X#define DEV_PREFIX ""
X#define DEV_INFIX "@"
X#define DEV_SUFFIX ":"
X#define DISK_SUFFIX ":c,raw"
X
Xstatic struct dev_info devi;
X
X/* Get number of ESP controllers */
Xstatic u_int get_nesp(){
X	return MAXESP;
X}
X
X/* 
X * Get path to specified esp device. Returned string is malloc'ed.
X * assumption: global variable devi points to esp device info.
X */
Xstatic char *get_devicepath(j)
Xint j;
X{
X	char *devicepath, *cp;
X
X	/* Grab the name (should be esp) */
X	devicepath=s(kernel_getstring((u_long)ddi_get_name(&devi)));
X	/* ... and the address */
X	cp=cat(devicepath,
X		"@",
X		kernel_getstring((u_long)ddi_get_addr(&devi)),
X		NULL);
X	free(devicepath);
X	devicepath=cp;
X	/*
X	 * At this point, devicepath should be esp@addr,addr. Now
X	 * trace backwards up the devinfo tree until we get to the
X	 * root. At each branch, record the name and address in
X	 * devicepath as in "...device@addr,addr/device@addr,addr/..."
X	 */
X	{
X		/* construct path */
X		struct dev_info di, *parent;
X		char *name;
X
X		for(parent=ddi_get_parent(&devi);
X		    NULL!=parent;
X		    parent=ddi_get_parent(&di)){
X			/* grab the parent */
X			if(-1==getkvm((u_long)parent,
X				&di, sizeof(di))){
X				Error("kvm_read: #%d parent %s", j,
X					devicepath);
X			}
X			/* get its name */
X			name=kernel_getstring((u_long)ddi_get_name(&di));
X
X			/* get the address, add both to devicepath */
X			if(DDI_CF1(&di)){
X				char *pathcomp, *newpath;
X
X				pathcomp=cat(name, "@", NULL);
X				name=kernel_getstring(
X					(u_long)ddi_get_addr(&di));
X				if(!*name){
X					free(pathcomp);
X				} else {
X					newpath = cat(pathcomp,
X							name,
X							"/",
X							devicepath,
X							NULL);
X					free(devicepath);
X					free(pathcomp);
X					devicepath=newpath;
X				}
X			}
X		}
X	}
X	/* almost done. just add "/devices/" to head of devicepath */
X	cp=cat("/devices/", devicepath, NULL);
X	free(devicepath);
X	devicepath=cp;
X
X	return(devicepath);
X}
X
X/* Get address of specified device. Note: returned in static storage */
Xstatic char *get_addr(di)
Xstruct dev_info *di;
X{
X	return(kernel_getstring((u_long)ddi_get_addr(di)));
X}
X
Xstatic void init_scsitarget(){}
X
Xstatic int get_scsiaddr(name, di, target, lun)
Xchar *name;
Xstruct dev_info *di;
Xint *target, *lun;
X{
X	struct scsi_device sd;
X
X	if(-1==getkvm((u_long)ddi_get_driver_private(di), &sd, sizeof(sd))){
X		return(-1);
X	}
X	*target = (int)sd.sd_address.a_target;
X	*lun = (int)sd.sd_address.a_lun;
X	return(0);
X}
END_OF_FILE
if test 4060 -ne `wc -c <'sunos5.h'`; then
    echo shar: \"'sunos5.h'\" unpacked with wrong size!
fi
# end of 'sunos5.h'
fi
if test ! -d 'sundev' ; then
    echo shar: Creating directory \"'sundev'\"
    mkdir 'sundev'
fi
if test -f 'sundev/dmaga.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'sundev/dmaga.h'\"
else
echo shar: Extracting \"'sundev/dmaga.h'\" \(0 characters\)
sed "s/^X//" >'sundev/dmaga.h' <<'END_OF_FILE'
END_OF_FILE
if test 0 -ne `wc -c <'sundev/dmaga.h'`; then
    echo shar: \"'sundev/dmaga.h'\" unpacked with wrong size!
fi
# end of 'sundev/dmaga.h'
fi
if test -f 'format.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'format.c'\"
else
echo shar: Extracting \"'format.c'\" \(5905 characters\)
sed "s/^X//" >'format.c' <<'END_OF_FILE'
X/*
X * format.c - code for providing format info, generating format.dat using
X *            uscsi queries.
X *
X * Author: John DiMarco,
X *         University of Toronto, Computing Disciplines Facility
X *         jdd@cdf.toronto.edu
X */
X
X#ifndef lint
Xstatic char rcsid[] = "$Header: /u/jdd/src/jdd/scsiinfo/RCS/format.c,v 3.7 1994/07/22 19:47:05 jdd Exp $";
X#endif
X
X/* 
X * $Log: format.c,v $
X * Revision 3.7  1994/07/22  19:47:05  jdd
X * print drive capacity in MB, or GB if drive is greater than 1GB
X *
X * Revision 3.6  1994/07/22  18:20:30  jdd
X * slight change to -f output to make it slightly more machine-parsable
X *
X * Revision 3.5  1994/07/22  15:03:45  jdd
X * open disk device with O_NDELAY so that open succeeds without a label.
X *
X * Revision 3.4  1994/07/18  17:07:19  jdd
X * if sector size is zero, assume 512 bytes
X *
X * Revision 3.4  1994/07/18  17:07:19  jdd
X * if sector size is zero, assume 512 bytes
X *
X * Revision 3.3  1994/05/09  18:34:17  jdd
X * C partition name in SunOS 5.x is "2", not "c".
X *
X * Revision 3.2  1994/02/14  20:53:41  jdd
X * Only print out trks_zone, asect, atrks if they differ from the default.
X * atrks is Alternate Tracks per volume, not per zone.
X *
X * Revision 3.1  1994/01/11  16:07:10  jdd
X * added support for -o (original) option
X *
X * Revision 3.0  1993/12/21  20:55:43  jdd
X * *** empty log message ***
X *
X *
X */
X
X#include <stdio.h>
X#include <fcntl.h>
X#include <sys/stat.h>
X#include "utils.h"
X#include "uscsi.h"
X
X#ifndef DTYPE_DIRECT
X#define DTYPE_DIRECT 0x00
X#endif /* DTYPE_DIRECT */
X
X#define MAX_RPM 14400
X#define MIN_RPM 3000
X#define VENDOR_SIZE 8
X#define PRODUCT_SIZE 16
X#define STANDARD_ACYL 2
X#define FUDGEFACTOR 1.15
X#define SECTORSIZE 512
X#define MD21 "MD21"
X#define SCSI "SCSI"
X
Xextern int d;
X
Xstatic int acyl = STANDARD_ACYL;
X
Xvoid format(formatdat, osversion, diskdevice, original)
Xint formatdat;
Xchar *osversion;
Xchar *diskdevice;
Xint original;
X{
X	struct stat sb;
X	int fd, i;
X	int devicetype;
X	char vendor[VENDOR_SIZE+1], product[PRODUCT_SIZE+1];
X	int capacity;
X	int nsect, sector_size;
X	int pcyl, nhead, rpm;
X	int trks_zone, atrks, asect;
X	char disk_type[VENDOR_SIZE+PRODUCT_SIZE+2], *ctlr, *cname;
X	int fmt_time, ncyl, bpt_, csize;
X
X	/* preliminary stuff */
X	if(d) printf("Generating format.dat for %s, SunOS %s\n", diskdevice,
X			osversion);
X	if(stat(diskdevice, &sb)<0){
X		perror(diskdevice);
X		Error("Cannot access device, giving up.");
X	}
X	if(!S_ISCHR(sb.st_mode)){
X		Error("%s must be a raw disk device.", diskdevice);
X	}
X	if(0>(fd=open(diskdevice, O_RDONLY|O_NDELAY))){
X		perror(diskdevice);
X		Error("Cannot open device, giving up.");
X	}
X
X	/* get vendor and product */
X	if(0>scsi_inquiry(fd, &devicetype, vendor, product)){
X		perror(diskdevice);
X		Error("SCSI INQUIRY failed, giving up.");
X	}
X	if(DTYPE_DIRECT!=devicetype){
X		Error("%s is not a disk.", diskdevice);
X	}
X
X	/* get number of blocks available */
X	if(0>scsi_capacity(fd, &capacity)){
X		perror(diskdevice);
X		Error("SCSI READ_CAPACITY failed, giving up.");
X	}
X
X	/* get nsect, sector_size, pcyl, nhead, rpm, disk_type, ctlr, 
X	   fmt_time, acyl, ncyl, bpt, trks_zone, atrks, asect */
X
X	if(0>scsi_modeinfo(fd, original, &nsect, &sector_size, &pcyl, &nhead, 
X		&rpm, &trks_zone, &asect, &atrks)){
X		perror(diskdevice);
X		Error("SCSI mode select failed, giving up.");
X	}
X	if(512 != sector_size){
X		if(sector_size){
X			Error(
X		"Drive is formatted with with sector size %d, should be %d",
X				sector_size, SECTORSIZE);
X		} else {
X			Warning("Drive claims sector size 0, using 512 bytes");
X			sector_size=512;
X		}
X	}
X	if(rpm>MAX_RPM || rpm<MIN_RPM){
X		Warning(
X	   "Drive claims to have strange RPM value %d, using 3600.", rpm);
X		rpm=3600;
X	}
X
X	vendor[VENDOR_SIZE]='\0';
X	for(i=VENDOR_SIZE-1;i>0 && vendor[i]==' ';i--){
X		vendor[i]='\0';
X	}
X	product[sizeof(product)-1]='\0';
X	for(i=PRODUCT_SIZE-1;i>0 && product[i]==' ';i--){
X		product[i]='\0';
X	}
X	sprintf(disk_type, "%s %s", vendor, product);
X
X	{
X		int osmajor=0, osminor=0, subosminor=0;
X
X		sscanf(osversion, "%d.%d.%d", &osmajor, &osminor, &subosminor);
X		if(4==osmajor && osminor<2 && subosminor<2){
X			ctlr=MD21;
X		} else {
X			ctlr=SCSI;
X		}
X		if(osmajor<5) {
X			cname="c";
X		} else {
X			cname="2";
X		}
X	}
X
X	fmt_time = (capacity / 1000000) + 1;
X
X	ncyl = (capacity / (nhead * nsect)) - acyl;
X
X	bpt_ = (int) (FUDGEFACTOR * SECTORSIZE) * nsect;
X
X	csize = ncyl*nhead*nsect;
X
X	if(formatdat){
X		printf("disk_type = \"%s\" \\\n", disk_type);
X		printf(  "\t: ctlr = %s : fmt_time = %d \\\n", ctlr, fmt_time);
X
X		/* only output the following if they're nondefault */
X		printf(  "\t");
X		if(1 != trks_zone) printf(": trks_zone = %d ", trks_zone);
X		if(nhead != atrks) printf(": atrks = %d ", atrks);
X		if(1 != asect) printf(" : asect = %d ", asect);
X		printf(" \\\n");
X
X		printf(  "\t: ncyl = %d : acyl = %d", ncyl, acyl);
X		printf(     " : pcyl = %d : nhead = %d", pcyl, nhead);
X		printf(     " : nsect = %d \\\n", nsect);
X
X		printf(  "\t: rpm = %d : bpt = %d\n", rpm, bpt_);
X
X		printf("\n");
X		printf("partition = \"%s\" \\\n", disk_type);
X		printf(  "\t: disk = \"%s\" : ctlr = %s \\\n", disk_type, ctlr);
X		printf(  "\t: %s = 0, %d\n", cname, csize);
X	} else {
X		printf("Vendor:                      %s\n", vendor);
X		printf("Model:                       %s\n", product);
X		printf("Formatted Capacity:          %d sectors ", capacity); 
X		if(capacity >= 2000000){
X			printf("(%.2f GB)\n", (float)capacity/2000000);
X		} else {
X			printf("(%.2f MB)\n", (float)capacity/2000);
X		}
X		printf("Sector size:                 %d bytes\n", sector_size);
X		printf("Physical Cylinders:          %d\n", pcyl);
X		printf("Heads:                       %d\n", nhead);
X		printf("Sectors per track (Avg.):    %d\n", nsect);
X		printf("Tracks per zone:             %d\n", trks_zone);
X		printf("Alternate Sectors per zone:  %d\n", asect);
X		printf("Alternate Tracks per volume: %d\n", atrks);
X		printf("Rotational speed:            %d rpm\n", rpm);
X	}
X}
END_OF_FILE
if test 5905 -ne `wc -c <'format.c'`; then
    echo shar: \"'format.c'\" unpacked with wrong size!
fi
# end of 'format.c'
fi
if test -f 'format.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'format.h'\"
else
echo shar: Extracting \"'format.h'\" \(281 characters\)
sed "s/^X//" >'format.h' <<'END_OF_FILE'
X/*
X * format.h - header file for format.c
X *
X * Author: John DiMarco, University of Toronto, CDF
X *         jdd@cdf.toronto.edu
X */
X
X/* 
X * $Log: format.h,v $
X * Revision 1.1  1993/12/21  20:55:59  jdd
X * Initial revision
X *
X *
X */
X
X/* Exported Procedures */
Xextern void format();
END_OF_FILE
if test 281 -ne `wc -c <'format.h'`; then
    echo shar: \"'format.h'\" unpacked with wrong size!
fi
# end of 'format.h'
fi
echo shar: End of shell archive.
exit 0
