Subject: Disklabels arrive for 2.11BSD (#262 part 13 of 18)
Index:	sys,bin,usr.lib,(many more)/<many> 2.11BSD

Description:
	The moving the partitions tables out of the disk drivers and to
	a disklabel residing on the media has been on the wish list for
	many many years.

	Disklabels have finally arrived for 2.11BSD!

Repeat-By:
	Observation.  Also a reading of the setup and installation
	documentation for previous 2BSD releases (2.9, 2.10, 2.11)
	all have a paragraph similar to this present:

"It is possible to change the partitions by changing the code for the
table in the disk driver.  Since it's desirable to do this, these tables
really should be read off each pack...."

Fix:
	This is part 13 of 18.  Gather all parts before doing anything
	except reading the instructions which are in #250 (part 1).

	Updated by this part are:

/usr/src/sys/pdpstand/M.s
/usr/src/sys/pdpstand/Makefile
/usr/src/sys/pdpstand/label.c
/usr/src/sys/pdpstand/boot.c
/usr/src/sys/pdpstand/br.c
/usr/src/sys/pdpstand/conf.c
/usr/src/sys/pdpstand/hk.c
/usr/src/sys/pdpstand/ht.c
/usr/src/sys/pdpstand/maketape.data
/usr/src/sys/pdpstand/mtboot.s
/usr/src/sys/pdpstand/prf.c
/usr/src/sys/pdpstand/ra.c
/usr/src/sys/pdpstand/rk.c
/usr/src/sys/pdpstand/rl.c
/usr/src/sys/pdpstand/saio.h
/usr/src/sys/pdpstand/si.c
/usr/src/sys/pdpstand/srt0.s
/usr/src/sys/pdpstand/sys.c
/usr/src/sys/pdpstand/tm.c
/usr/src/sys/pdpstand/tmscp.c
/usr/src/sys/pdpstand/ts.c
/usr/src/sys/pdpstand/xp.c
/usr/src/sys/pdpstand/displaylab.c
/usr/src/sys/pdpstand/disklabel.c

	label.c, disklabel.c, and displaylab.c are NEW and are added
	by upacking the shar file included below.

	Essentially the standalone system was rewritten.  The changes
	are large and widespread.  Almost everything about the standalone
	i/o system is different.

	The major changes are:

		disklabel support (for MSCP and RL drives).

		routines to read and write disklabels.

		Best of all - a standalone disklabel program that attempts
		to be "sysadmin friendly".  This program is now the 1st
		program on the tape (right after boot).

		The capability to load split I/D executables from tape.
		This was required for 'restor' because the disklabel support
		added too much code+data to fit 'restor' in 48kb.

		Tape drivers can now do "seek" operations!  This was a major
		pain but required for loading split I/D executables.  Such
		executables are loaded in two steps - first the data, and then
		the code.  Normal executables are loaded in one sequential 
		read.  

		NOTE: seeking on tape only works for 1kb record sizes.  That
		      is the record size used for executables on the tape.

		Although not strictly required (yet) the 'icheck' program
		is built split I/D.  As more drivers are converted to
		support labels the space required would have driven icheck
		over the 48kb limit soon or later.

		The split I/D support meant that the I/O address calculation
		had to change - simply using 'segflag' as the top two bits of
		an 18 bit UNIBUS address no longer was the correct thing to
		do in all cases.

		As a result of the change above it is no longer necessary
		to load /boot on a 64kb boundary!  Boot must still be
		loaded below 256kb (for reasons to do with UNIBUS mapping)
		but if necessary Boot could be loaded above 192kb.

		The layout of a bootable tape has changed slightly.  There is
		an additional standalone program - disklabel, present.  The
		layout of the tape is now:

			file	program
			----	-------
			0	bootblock + boot
			1	disklabel
			2	mkfs
			3	restor
			4	icheck
			5	dump of root filesystem
			6	tar file
			7	tar file
			8	tar file

		The message from Boot and how to specify which image to
		boot have changed.  UNLESS you are booting from a second
		(or third) controller you will not notice much of a difference.

		Basically the format of the string entered at the ':' prompt
		is of the form:

			: ra(c,u,p)file

		where 'c' is the controller number (0-3), 'u' is the unit
		number (0-7) and 'p' is the partition number (0-7).

		The old method of embedding the controller number in the
		unit number is gone.  Previously to boot from the second
		MSCP controller you used the string "ra(64,0)unix".  The
		new string would be "ra(1,0,0)unix".

	At this time only the MSCP and RL drivers implement labels.  
	The 'xp' (SMD) driver is the next in line to be converted at which 
	time a much smaller update kit will be posted.

	ONLY the TMSCP and TS tape drivers have been tested as far as
	'seek'ing - they're the only ones I have.  The other drivers should 
	work, the changes were straight forward but...  If  you do have
	a problem with the HT (TU16) or TM (TU10) drivers let me know and
	we'll try to work something out.

	Cut where indicated and save to a file (/tmp/262).  Then:

		cd /tmp
		sh 262
		sh pdpstand.shar
		patch -p0 < pdpstand.patch
		rm pdpstand.shar pdpstand.patch

------------------------------cut here---------------------------------
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
#	pdpstand.shar
#	pdpstand.patch
# This archive created: Mon Jul 10 23:29:03 1995
export PATH; PATH=/bin:/usr/bin:$PATH
if test -f 'pdpstand.shar'
then
	echo shar: "will not over-write existing file 'pdpstand.shar'"
else
sed 's/^Y//' << \SHAR_EOF > 'pdpstand.shar'
Y#! /bin/sh
Y# This is a shell archive, meaning:
Y# 1. Remove everything above the #! /bin/sh line.
Y# 2. Save the resulting text in a file.
Y# 3. Execute the file with /bin/sh (not csh) to create:
Y#	/usr/src/sys/pdpstand/label.c
Y#	/usr/src/sys/pdpstand/displaylab.c
Y#	/usr/src/sys/pdpstand/disklabel.c
Y# This archive created: Mon Jul 10 23:27:56 1995
Yexport PATH; PATH=/bin:/usr/bin:$PATH
Yif test -f '/usr/src/sys/pdpstand/label.c'
Ythen
Y	echo shar: "will not over-write existing file '/usr/src/sys/pdpstand/label.c'"
Yelse
Ysed 's/^X//' << \SHAR_EOF > '/usr/src/sys/pdpstand/label.c'
YX/*-
YX * Public domain, May 1995
YX *
YX *	@(#)label.c	1.0 (2.11BSD GTE) 1995/06/08
YX */
YX
YX#include "../h/param.h"
YX#include "saio.h"
YX
YX/*
YX * Called from the general device label routine in conf.c.   A label with
YX * a fake geometry suitable for reading the label sector is created and
YX * the driver's strategy routine is called.  If the label is corrupted
YX * or absent an error is possibly printed.
YX *
YX * NOTES:  We reuse the iob structure's buffer (i_buf).
YX *	   All disks must have at least LABELSECTOR+1 sectors in a track.
YX *	   (this is not expected to be a problem since LABELSECTOR is 1).
YX*/
YX
YXreadlabel(io, strat, name)
YX	struct	iob	*io;
YX	int	(*strat)();
YX	char	*name;
YX	{
YX	struct disklabel *lp = &io->i_label;
YX
YX	io->i_bn = LABELSECTOR;
YX	io->i_ma = io->i_buf;
YX	io->i_cc = 512;			/* XXX */
YX	lp->d_nsectors = LABELSECTOR + 1;	/* # sectors per track */
YX	lp->d_ntracks = 1;			/* # tracks per cylinder */
YX	lp->d_secpercyl = LABELSECTOR + 1;	/* # sectors per cylinder */
YX	if	((*strat)(io, READ) != 512)
YX		{
YX		printf("%s%d,%d: error reading labelsector\n", name,
YX			io->i_ctlr, io->i_unit);
YX		return(-1);
YX		}
YX	bcopy(io->i_buf, lp, sizeof (struct disklabel));
YX	if	(Nolabelerr)
YX		return(0);
YX	if	(lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC ||
YX		 dkcksum(lp) != 0)
YX		{
YX		printf("%s%d,%d disklabel missing or corrupt\n", name,
YX			io->i_ctlr, io->i_unit);
YX		return(-1);
YX		}
YX	return(0);
YX	}
YX
YXwritelabel(io, strat, name)
YX	register struct	iob	*io;
YX	int	(*strat)();
YX	char	*name;
YX	{
YX	register struct disklabel *lp = &io->i_label;
YX
YX	if	((io->i_flgs & F_WRITE) == 0)
YX		return(-1);
YX	io->i_bn = LABELSECTOR;
YX	io->i_ma = (char *)&io->i_label;
YX	io->i_cc = 512;			/* XXX */
YX/*
YX * The geometry had better be set up and correct at this point - we can not
YX * fake the geometry because that would overwrite the contents of the label
YX * itself.
YX*/
YX	lp->d_secsize = 512;			/* XXX */
YX	lp->d_magic = DISKMAGIC;
YX	lp->d_magic2 = DISKMAGIC;
YX	lp->d_checksum = 0;
YX	lp->d_checksum = dkcksum(lp);
YX
YX	if	((*strat)(io, WRITE) != 512)
YX		{
YX		printf("%s: error writing labelsector\n", name);
YX		return(-1);
YX		}
YX	return(0);
YX	}
YX/*
YX * Compute checksum for disk label.
YX */
YXdkcksum(lp)
YX	register struct disklabel *lp;
YX	{
YX	register u_short *start, *end;
YX	register u_short sum = 0;
YX
YX	start = (u_short *)lp;
YX	end = (u_short *)&lp->d_partitions[lp->d_npartitions];
YX	while (start < end)
YX		sum ^= *start++;
YX	return (sum);
YX	}
YX
YX/*
YX * Check for partitions which overlap each other.  While it is legal
YX * to have partitions which overlap (as long as they are not used at the
YX * same time) it is often a mistake or oversite. 
YX*/
YX
YXoverlapchk(lp)
YX	register struct disklabel *lp;
YX	{
YX	register struct partition *pp;
YX	int	i, part, openmask;
YX	daddr_t	start, end;
YX
YX#define	RAWPART	2
YX/*
YX * 'c' is normally (but not always) the partition which spans the whole
YX * drive, thus it is not normally an error for it to overlap all other 
YX * partitions.
YX*/
YX	openmask = ~0 & ~(1 << RAWPART);
YX	for	(part = 0; part < lp->d_npartitions; part++)
YX		{
YX		pp = &lp->d_partitions[part];
YX		if	(part == RAWPART || pp->p_size == 0)
YX			continue;
YX		start = pp->p_offset;
YX		end = start + pp->p_size;
YX
YX		for	(pp = lp->d_partitions, i = 0; 
YX			 i < lp->d_npartitions;
YX			 pp++, i++)
YX			{
YX/*
YX * We make sure to not report zero length partitions or that a 
YX * partition overlaps itself.  We've already checked lower partitions
YX * so avoid giving something like "a overlaps b" and then "b overlaps a".
YX*/
YX			if	(i <= part || pp->p_size == 0)
YX				continue;
YX			if	(pp->p_offset + pp->p_size <= start ||
YX				 pp->p_offset >= end)
YX				continue;
YX			if	((openmask & (1 << i)) == 0)
YX				continue;
YX			printf("warning: partition '%c' overlaps '%c'\n",
YX				'a' + part, 'a' + i);
YX			}
YX		}
YX	}
YSHAR_EOF
Yfi
Yif test -f '/usr/src/sys/pdpstand/displaylab.c'
Ythen
Y	echo shar: "will not over-write existing file '/usr/src/sys/pdpstand/displaylab.c'"
Yelse
Ysed 's/^X//' << \SHAR_EOF > '/usr/src/sys/pdpstand/displaylab.c'
YX/*
YX * 1995/06/08 - Borrowed from disklabel.c
YX *
YX * Many of the unused or invariant fields are omitted from the display.  This
YX * has the benefit of having everything fit on one screen - important since
YX * the standalone console driver does not do xon/xoff.
YX *
YX *  The partition display is jagged because the minimal printf() function
YX * does not do field padding or justification.
YX*/
YX
YX#define	DKTYPENAMES
YX#include <sys/param.h>
YX#include "saio.h"
YX
YXdisplaylabel(lp)
YX	register struct disklabel *lp;
YX	{
YX	register int i;
YX	register struct partition *pp;
YX	char	junk[32];
YX
YX	putchar('\n');
YX	if	(lp->d_type < DKMAXTYPES)
YX		printf("type: %s\n", dktypenames[lp->d_type]);
YX	else
YX		printf("type: %d\n", lp->d_type);
YX	strncpy(junk, lp->d_typename, sizeof (lp->d_typename));
YX	junk[sizeof(lp->d_typename)] = '\0';
YX	printf("disk: %s\n", junk);
YX
YX	strncpy(junk, lp->d_packname, sizeof (lp->d_packname));
YX	junk[sizeof(lp->d_packname)] = '\0';
YX	printf("label: %s\n", junk);
YX
YX	printf("flags:");
YX	if	(lp->d_flags & D_REMOVABLE)
YX		printf(" removeable");
YX	if	(lp->d_flags & D_ECC)
YX		printf(" ecc");
YX	if	(lp->d_flags & D_BADSECT)
YX		printf(" badsect");
YX	printf("\n");
YX	printf("bytes/sector: %d\n", lp->d_secsize);
YX	printf("sectors/track: %d\n", lp->d_nsectors);
YX	printf("tracks/cylinder: %d\n", lp->d_ntracks);
YX	printf("sectors/cylinder: %d\n", lp->d_secpercyl);
YX	printf("cylinders: %d\n", lp->d_ncylinders);
YX	printf("rpm: %d\n", lp->d_rpm);
YX	printf("drivedata: ");
YX	for	(i = 0; i < NDDATA; i++)
YX		printf("%D ", lp->d_drivedata[i]);
YX	printf("\n\n%d partitions:\n", lp->d_npartitions);
YX	printf("#        size   offset    fstype   [fsize bsize]\n");
YX	pp = lp->d_partitions;
YX	for	(i = 0; i < lp->d_npartitions; i++, pp++)
YX		{
YX		if	(pp->p_size == 0)
YX			continue;
YX		printf("  %c: %D %D  ", 'a' + i,
YX			pp->p_size, pp->p_offset);
YX		if	((unsigned) pp->p_fstype < FSMAXTYPES)
YX			printf("%s", fstypenames[pp->p_fstype]);
YX		else
YX			printf("%d", pp->p_fstype);
YX		switch	(pp->p_fstype)
YX			{
YX			case FS_V71K:
YX			case FS_UNUSED:
YX				printf("    %d %d ", pp->p_fsize,
YX					pp->p_fsize * pp->p_frag);
YX				break;
YX			default:
YX				printf("               ");
YX				break;
YX			}
YX		printf("\t# (Cyl. %D", pp->p_offset / lp->d_secpercyl);
YX		if	(pp->p_offset % lp->d_secpercyl)
YX			putchar('*');
YX		else
YX			putchar(' ');
YX		printf("- %D",
YX			(pp->p_offset + 
YX			pp->p_size + lp->d_secpercyl - 1) /
YX			lp->d_secpercyl - 1);
YX		if	(pp->p_size % lp->d_secpercyl)
YX			putchar('*');
YX		printf(")\n");
YX		}
YX	putchar('\n');
YX	}
YSHAR_EOF
Yfi
Yif test -f '/usr/src/sys/pdpstand/disklabel.c'
Ythen
Y	echo shar: "will not over-write existing file '/usr/src/sys/pdpstand/disklabel.c'"
Yelse
Ysed 's/^X//' << \SHAR_EOF > '/usr/src/sys/pdpstand/disklabel.c'
YX/*
YX * Public domain, June 1995
YX *
YX *	@(#)disklabel.c	1.2 (2.11BSD GTE) 1995/07/10
YX*/
YX
YX#define	DKTYPENAMES
YX#include "../h/param.h"
YX#include "saio.h"
YX
YX	int	Nolabelerr = 1;		/* Inhibit spurious label error msgs */
YX	char	module[] = "disklabel";	/* This program's name */
YX	char	line[80], device[80];
YX
YXextern	long	atol();
YXextern	struct	iob	iob[];
YXextern	struct	devsw	devsw[];
YX
YXmain()
YX	{
YX	register int	f;
YX	register struct	disklabel *lp;
YX	struct	iob	*io;
YX
YX	printf("%s\n", module);
YX
YX	while	(1)
YX		{
YX		printf("Disk? ");
YX		gets(line);
YX		if	(!line[0])
YX			continue;
YX		strcpy(device, line);
YX		f = open(device, F_WRITE);
YX		if	(f < 0)
YX			{
YX			printf("Error opening '%s' for writing\n", device);
YX			continue;
YX			}
YX		io = &iob[f - 3];
YX		if	(io->i_flgs & F_TAPE)
YX			{
YX			printf("Can not label tapes.\n");
YX			continue;
YX			}
YX		break;
YX		}
YX/*
YX * The open() will have retrieved the label sector.  This explicit read
YX * is for debugging and testing because the driver's open routine may be
YX * under development and the automatic retrieval of the label is commented
YX * out.
YX*/
YX	if	(devlabel(io, READLABEL) < 0)
YX		{
YX		printf("Can not read label sector from '%s'\n", device);
YX		return;		/* back to Boot */
YX		}
YX	lp = &io->i_label;
YX	if	(lp->d_magic != DISKMAGIC || lp->d_magic2 != DISKMAGIC ||
YX		 dkcksum(lp))
YX		{
YX		printf("'%s' is unlabeled or the label is corrupt.\n", device);
YX		printf("Proceed? [y/n] ");
YX		if	(gyon() == 'n')
YX			return;		/* back to Boot */
YX/*
YX * We next call the driver's entry which attempts to identify the drive
YX * and set up a default (1 partition) label with the best guess as to
YX * geometry, etc.  If this call fails then the driver does not support
YX * labels ('nullsys' is being used in the device table).
YX*/
YX		if	(devlabel(io, DEFAULTLABEL) < 0)
YX			{
YX			printf("The '%s' driver does not support labels.\n",
YX				devsw[io->i_ino.i_dev].dv_name);
YX			return;		/* back to Boot */
YX			}
YX		}
YX	doit(io);
YX	return;
YX	}
YX
YXdoit(io)
YX	register struct iob *io;
YX	{
YX	int	c, dirty = 0;
YX	struct	disklabel *lp = &io->i_label;
YX
YX	while	(1)
YX		{
YX		printf("d(isplay) D(efault) m(odify) w(rite) q(uit)? ");
YX		c = egetchar("dDmwq");
YX		switch	(c)
YX			{
YX			case	'm':
YX				modifylabel(lp);
YX				overlapchk(lp);
YX				(void)checklabel(lp);
YX/*
YX * We make the assumption that the label was modified - the dirty
YX * flag is set so we can ask if the changes should be discarded on a 'q'.
YX*/
YX				dirty = 1;
YX				break;
YX			case	'w':
YX				overlapchk(lp);
YX				(void)checklabel(lp);
YX				devlabel(io, WRITELABEL);
YX/*
YX * Changed label was committed to disk so we can clear the dirty flag now
YX * and not ask the user if the changes should be kept when a 'q'uit is done.
YX*/
YX				dirty = 0;
YX				break;
YX			case	'd':
YX				displaylabel(lp);
YX				break;
YX			case	'D':
YX				devlabel(io, DEFAULTLABEL);
YX				dirty = 1;
YX				break;
YX			case	'q':
YX				if	(!dirty)
YX					return;
YX				printf("Label changed. Discard changes [y/n]? ");
YX				if	(gyon() == 'n')
YX					break;
YX				return;
YX			default:
YX				break;
YX			}
YX		}
YX/* NOTREACHED */
YX	}
YX
YXmodifylabel(lp)
YX	register struct disklabel *lp;
YX	{
YX	register int	c;
YX
YX	while	(1)
YX		{
YX		printf("modify\n");
YX		printf("d(isplay) g(eometry) m(isc) p(artitions) q(uit)? ");
YX		c = egetchar("dgmpq");
YX		switch	(c)
YX			{
YX			case	'd':
YX				displaylabel(lp);
YX				break;
YX			case	'g':
YX				dogeometry(lp);
YX				break;
YX			case	'm':
YX				domisc(lp);
YX				break;
YX			case	'p':
YX				dopartitions(lp);
YX				break;
YX			case	'q':
YX				return;
YX			default:
YX				break;
YX			}
YX		}
YX/* NOTREACHED */
YX	}
YX
YXdogeometry(lp)
YX	struct	disklabel *lp;
YX	{
YX	register int c;
YX
YX	while	(1)
YX		{
YX		printf("modify geometry\n");
YX		printf("d(isplay) s(ector/trk) t(rk/cyl) c(yl) S(ector/cyl) q(uit)? ");
YX		c = egetchar("dstcSq");
YX		switch	(c)
YX			{
YX			case	'd':
YX				displaylabel(lp);
YX				break;
YX			case	's':
YX				fillin_int(&lp->d_nsectors,
YX					"sectors/track [%d]: ", 512);
YX				break;
YX			case	't':
YX				fillin_int(&lp->d_ntracks,
YX					"tracks/cylinder [%d]: ", 127);
YX				break;
YX			case	'c':
YX				fillin_int(&lp->d_ncylinders,
YX					"cylinders [%d]: ", 4096);
YX				break;
YX			case	'S':
YX				lp->d_secpercyl= lp->d_nsectors * lp->d_ntracks;
YX				fillin_int(&lp->d_secpercyl,
YX					"sectors/cylinder [%d]: ", 65535);
YX				break;
YX			case	'q':
YX				if	(lp->d_secpercyl == 0)
YX					lp->d_secpercyl = lp->d_nsectors *
YX							lp->d_ntracks;
YX				lp->d_secperunit = (long)lp->d_ncylinders * 
YX							lp->d_secpercyl;
YX				return;
YX			default:
YX				break;
YX			}
YX		}
YX/* NOTREACHED */
YX	}
YX
YXdomisc(lp)
YX	register struct disklabel *lp;
YX	{
YX	register int c;
YX	char	junk[32];
YX
YX	while	(1)
YX		{
YX		printf("modify misc\n");
YX		printf("d(isplay) t(ype) n(ame) l(abel) f(lags) r(pm) D(rivedata) q(uit)? ");
YX		c = egetchar("dtnlfrDq");
YX		switch	(c)
YX			{
YX			case	'd':
YX				displaylabel(lp);
YX				break;
YX			case	't':
YX				if	(lp->d_type >= DKMAXTYPES)
YX					lp->d_type = 0;
YX				printf("type [%s]: ", dktypenames[lp->d_type]);
YX				gets(line);
YX				if	(line[0])
YX					lp->d_type = findtype(dktypenames,
YX								line,
YX								lp->d_type);
YX				break;
YX			case	'n':
YX				strncpy(junk, lp->d_typename,
YX						sizeof (lp->d_typename));
YX				junk[sizeof (lp->d_typename)] = '\0';
YX				printf("disk [%s]: ", junk);
YX				gets(line);
YX				if	(line[0])
YX					strncpy(lp->d_typename, line,
YX						sizeof (lp->d_typename));
YX				break;
YX			case	'l':
YX				strncpy(junk, lp->d_packname,
YX						sizeof (lp->d_packname));
YX				junk[sizeof (lp->d_packname)] = '\0';
YX				printf("label [%s]: ", junk);
YX				gets(line);
YX				if	(line[0])
YX					strncpy(lp->d_packname, line,
YX						sizeof (lp->d_packname));
YX				break;
YX			case	'f':
YX				doflags(lp);
YX				break;
YX			case	'r':
YX				fillin_int(&lp->d_rpm, "rpm [%d]: ", 32767);
YX				break;
YX			case	'D':
YX				dodrivedata(lp);
YX				break;
YX			case	'q':
YX				return;
YX			default:
YX				break;
YX			}
YX		}
YX/* NOTREACHED */
YX	}
YX
YXdodrivedata(lp)
YX	struct disklabel *lp;
YX	{
YX	register u_long *ulp;
YX	register int	i;
YX
YX	for	(i = 0, ulp = lp->d_drivedata; i < NDDATA; i++, ulp++)
YX		{
YX		printf("modify misc drivedata\n");
YX		printf("drivedata #%d [%D]: ", i, *ulp);
YX		gets(line);
YX		if	(line[0])
YX			*ulp = atol(line);
YX		}
YX	return;
YX	}
YX
YXdoflags(lp)
YX	register struct disklabel *lp;
YX	{
YX	register int	c;
YX
YX	while	(1)
YX		{
YX		printf("modify misc flags\n");
YX		printf("d(isplay) c(lear) e(cc) b(adsect) r(emovable) q(uit)? ");
YX		c = egetchar("dcerbq");
YX		switch	(c)
YX			{
YX			case	'c':
YX				lp->d_flags = 0;
YX				break;
YX			case	'd':
YX				displaylabel(lp);
YX				break;
YX			case	'r':
YX				lp->d_flags |= D_REMOVABLE;
YX				break;
YX			case	'e':
YX				lp->d_flags |= D_ECC;
YX				break;
YX			case	'b':
YX				lp->d_flags |= D_BADSECT;
YX				break;
YX			case	'q':
YX				return;
YX			default:
YX				break;
YX			}
YX		}
YX/* NOTREACHED */
YX	}
YX
YXdopartitions(lp)
YX	struct	disklabel *lp;
YX	{
YX	register int	c;
YX	int	i;
YX
YX	while	(1)
YX		{
YX		printf("modify partitions\n");
YX		printf("d(isplay) n(umber) s(elect) q(uit)? ");
YX		c = egetchar("dsnq");
YX		switch	(c)
YX			{
YX			case	'd':
YX				displaylabel(lp);
YX				break;
YX			case	'n':
YX				printf("Number of partitions (%d max) [%d]? ",
YX					MAXPARTITIONS, lp->d_npartitions);
YX				gets(line);
YX				if	(line[0] == '\0')
YX					i = lp->d_npartitions;
YX				else
YX					i = atoi(line);
YX				if	(i > 0 && i <= MAXPARTITIONS)
YX					lp->d_npartitions = i;
YX				break;
YX			case	's':
YX				printf("a b c d e f g h q(uit)? ");
YX				i = getpartnum();
YX				if	(i < 0)
YX					break;
YX				if	(i > lp->d_npartitions)
YX					lp->d_npartitions = i + 1;
YX				dopartmods(lp, i);
YX				break;
YX			case	'q':
YX				return;
YX			default:
YX				break;
YX			}
YX		}
YX/* NOTREACHED */
YX	}
YX
YXdopartmods(lp, part)
YX	struct	disklabel *lp;
YX	int	part;
YX	{
YX	char	pname = 'a' + part;
YX	int	i, c;
YX	register struct partition *pp = &lp->d_partitions[part];
YX	u_int	cyl;
YX	daddr_t	off, sec, size;
YX
YX	printf("sizes and offsets may be given as sectors, cylinders\n");
YX	printf("or cylinders plus sectors:  6200, 32c, 19c10s respectively\n");
YX
YX	while	(1)
YX		{
YX		printf("modify partition '%c'\n", pname);
YX		printf("d(isplay) z(ero) t(ype) o(ffset) s(ize) f(rag) F(size) q(uit)? ");
YX		c = egetchar("dztosfFq");
YX		switch	(c)
YX			{
YX			case	'z':
YX				pp->p_size = 0;
YX				pp->p_offset = 0;
YX				pp->p_fstype = FS_UNUSED;
YX				break;
YX			case	'd':
YX				displaylabel(lp);
YX				break;
YX			case	't':
YX				if	(pp->p_fstype >= FSMAXTYPES)
YX					pp->p_fstype = FS_UNUSED;
YX				printf("'%c' fstype [%s]: ", pname,
YX					fstypenames[pp->p_fstype]);
YX				gets(line);
YX				if	(line[0])
YX					pp->p_fstype = findtype(fstypenames,
YX								line,
YX								pp->p_fstype);
YX				break;
YX			case	'o':
YX				printf("'%c' offset [%D]: ",pname,pp->p_offset);
YX				gets(line);
YX				if	(line[0] == '\0')
YX					break;
YX				i = parse_sec_cyl(lp, line, &sec, &cyl);
YX				if	(i < 0)
YX					break;
YX				if	(cyl)
YX					off = lp->d_secpercyl * cyl;
YX				else
YX					off = 0;
YX				off += sec;
YX				pp->p_offset = off;
YX				break;
YX			case	's':
YX				printf("'%c' size [%D]: ", pname, pp->p_size);
YX				gets(line);
YX				if	(line[0] == '\0')
YX					break;
YX				i = parse_sec_cyl(lp, line, &sec, &cyl);
YX				if	(i < 0)
YX					break;
YX				if	(cyl)
YX					size = lp->d_secpercyl * cyl;
YX				else
YX					size = 0;
YX				size += sec;
YX				pp->p_size = size;
YX				break;
YX			case	'f':
YX				printf("'%c' frags/fs-block [1]: ", pname);
YX				gets(line);
YX				if	(line[0] == '\0')
YX					break;
YX				i = atoi(line);
YX				if	(i <= 0 || i > 255)
YX					{
YX					printf("frags/block <= 0 || > 255\n");
YX					pp->p_frag = 1;
YX					}
YX				else
YX					pp->p_frag = i;
YX				break;
YX			case	'F':	/* Not really used at the present */
YX				printf("'%c' frag size [1024]: ", pname);
YX				gets(line);
YX				if	(line[0] == '\0')
YX					break;
YX				i = atoi(line);
YX				if	(i <= 0 || (i % NBPG))
YX					{
YX					printf("fragsize <= 0 || ! % NBPG\n");
YX					pp->p_fsize = 0;
YX					}
YX				else
YX					pp->p_fsize = i;
YX				break;
YX			case	'q':
YX				if	(pp->p_fsize == 0)
YX					pp->p_fsize = 1024;
YX				if	(pp->p_frag == 0)
YX					pp->p_frag = 1;
YX				return;
YX			default:
YX				break;
YX			}
YX		}
YX/* NOTREACHED */
YX	}
YX
YXgetpartnum()
YX	{
YX	register int c;
YX	
YX	c = egetchar("abcdefghq");
YX	if	(c == 'q')
YX		return(-1);
YX	return(c - 'a');
YX	}
YX
YXfindtype(list, name, deflt)
YX	char	**list;
YX	char	*name;
YX	int	deflt;
YX	{
YX	register char **cpp;
YX	int	i;
YX
YX	for	(i = 0, cpp = list; *cpp; cpp++, i++)
YX		{
YX		if	(strcmp(*cpp, name) == 0)
YX			return(i);
YX		}
YX	printf("%s not found in list.  The possible choices are:\n\n", name);
YX	for	(cpp = list; *cpp; cpp++)
YX		printf("  %s\n", *cpp);
YX	putchar('\n');
YX	return(deflt);
YX	}
YX
YX/*
YX * Sizes and offsets can be specified in four ways:
YX *
YX *    Number of sectors:  32678
YX *    Number of cylinders:  110c
YX *    Number of cylinders and sectors:  29c14s
YX *    Number of sectors and cylinders:  22s134c
YX * 
YX * The trailing 's' or 'c' can be left off in the last two cases.
YX *
YX * The geometry section of the label must have been filled in previously.
YX * A warning is issued if the cylinder or cylinder+sector forms are used
YX * and the necessary geometry information is not present.
YX*/
YX
YXparse_sec_cyl(lp, line, sec, cyl)
YX	struct	disklabel *lp;
YX	char	line[];
YX	daddr_t	*sec;
YX	u_int	*cyl;
YX	{
YX	register char	*cp;
YX	int	error = 0;
YX	long	tmp, tmpcyl = 0, tmpsec = 0;
YX
YX	for	(tmp = 0, cp = line; *cp; cp++)
YX		{
YX		if	(*cp >= '0' && *cp <= '9')
YX			{
YX			tmp *= 10;
YX			tmp += (*cp - '0');
YX			}
YX		else if	(*cp == 'c')
YX			{
YX			if	(tmpcyl)
YX				{
YX				printf("duplicate 'c'ylinder specified\n");
YX				error = 1;
YX				break;
YX				}
YX			tmpcyl = tmp;
YX			tmp = 0;
YX			}
YX		else if	(*cp == 's')
YX			{
YX			if	(tmpsec)
YX				{
YX				printf("duplicate 's'ector specified\n");
YX				error = 1;
YX				break;
YX				}
YX			tmpsec = tmp;
YX			tmp = 0;
YX			}
YX		else
YX			{
YX			printf("illegal character '%c'\n", *cp);
YX			error = 1;
YX			break;
YX			}
YX		}
YX	if	(error)
YX		return(-1);
YX
YX/*
YX * At this point if either a 's' or 'c' was encountered in the string then
YX * one or both of 'tmpsec' and 'tmpcyl' will be non-zero.  If the trailing 
YX * character was omitted we need to figure out which variable gets the 
YX * contents left in 'tmp' when the terminating null character was seen. This
YX * is because "15c8" and "18s3" are both valid and indicate "15 cylinders +
YX * 8 sectors" and "18 sectors + 3 cylinders" respectively.
YX *
YX * If neither 'tmpsec' or 'tmpcyl' are nonzero then we have a simple sector
YX * number in 'tmp'.
YX*/
YX	if	(tmpsec || tmpcyl)
YX		{
YX		if	(tmpsec)
YX			tmpcyl = tmp;
YX		else
YX			tmpsec = tmp;
YX		}
YX	else
YX		{
YX		tmpsec = tmp;
YX		tmpcyl = 0;
YX		}
YX/*
YX * It is an error condition to specify a number of cylinders and not
YX * have previously defined the geometry - it is impossible to calculate
YX * the number of sectors in the partition without geometry.
YX*/
YX	if	(tmpcyl && lp->d_secpercyl == 0)
YX		{
YX		printf("# cylinders specified but no geometry info present!\n");
YX		return(-1);
YX		}
YX
YX/*
YX * Sanity check to make sure erroneous number of cylinders is not believed
YX * due to truncation (number of cylinders is really a 'u_int')
YX*/
YX
YX	if	(tmpcyl > 65535L)
YX		{
YX		printf("Number of cylinders specified (%D) is ridiculous!\n",
YX			tmpcyl);
YX		return(-1);
YX		}
YX	*cyl = (u_int)tmpcyl;
YX	*sec = tmpsec;
YX	return(0);
YX	}
YX
YXfillin_int(where, fmt, limit)
YX	u_int	*where;
YX	char	*fmt;
YX	u_int	limit;
YX	{
YX	u_int	i;
YX
YX	printf(fmt, *where);
YX	gets(line);
YX	if	(line[0])
YX		{
YX		i = (u_int)atoi(line);
YX		if	(i > limit)
YX			{
YX			printf("%d is out of bounds (> %d)\n", i, limit);
YX			return;
YX			}
YX		*where = i;
YX		}
YX	}
YX
YXfillin_long(where, fmt, limit)
YX	u_long	*where;
YX	char	*fmt;
YX	u_long	limit;
YX	{
YX	u_long	l;
YX
YX	printf(fmt, *where);
YX	gets(line);
YX	if	(line[0])
YX		{
YX		l = (u_int)atol(line);
YX		if	(l > limit)
YX			{
YX			printf("%D is out of bounds (> %D)\n", l, limit);
YX			return;
YX			}
YX		*where = l;
YX		}
YX	}
YX
YXgyon()
YX	{
YX	register int	c;
YX
YX	c = egetchar("yYnN");
YX	if	(c >= 'A' && c <= 'Z')
YX		c += ('a' - 'A');
YX	return(c);
YX	}
YX
YXegetchar(str)
YX	char	*str;
YX	{
YX	register int c;
YX
YX	while	(1)
YX		{
YX		c = getchar();
YX		if	(index(str, c))
YX			break;
YX		putchar('\007');
YX		}
YX	putchar(c);
YX	putchar('\n');
YX	return(c);
YX	}
YX
YX/*
YX * Check disklabel for errors and fill in
YX * derived fields according to supplied values.
YX *
YX * Adapted from the disklabel utility.
YX */
YXchecklabel(lp)
YX	register struct disklabel *lp;
YX	{
YX	register struct partition *pp;
YX	int i, errors = 0;
YX	char part;
YX
YX	if	(lp->d_nsectors == 0)
YX		{
YX		printf("sectors/track %d\n", lp->d_nsectors);
YX		return(1);
YX		}
YX	if	(lp->d_ntracks == 0)
YX		{
YX		printf("tracks/cylinder %d\n", lp->d_ntracks);
YX		return(1);
YX		}
YX	if	(lp->d_ncylinders == 0)
YX		{
YX		printf("cylinders/unit %d\n", lp->d_ncylinders);
YX		errors++;
YX		}
YX	if	(lp->d_rpm == 0)
YX		Warning("revolutions/minute %d", lp->d_rpm);
YX	if	(lp->d_secpercyl == 0)
YX		lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks;
YX	if	(lp->d_secperunit == 0)
YX		lp->d_secperunit = (long) lp->d_secpercyl * lp->d_ncylinders;
YX
YX	for	(i = 0; i < lp->d_npartitions; i++)
YX		{
YX		part = 'a' + i;
YX		pp = &lp->d_partitions[i];
YX		if	(pp->p_size == 0 && pp->p_offset != 0)
YX			Warning("partition %c: size 0, but offset %d",
YX			    part, pp->p_offset);
YX#ifdef notdef
YX		if (pp->p_size % lp->d_secpercyl)
YX			Warning("partition %c: size %% cylinder-size != 0",
YX			    part);
YX		if (pp->p_offset % lp->d_secpercyl)
YX			Warning("partition %c: offset %% cylinder-size != 0",
YX			    part);
YX#endif
YX		if	(pp->p_offset > lp->d_secperunit)
YX			{
YX			printf("partition %c: offset past end of unit %D %D\n",
YX				part, pp->p_offset, lp->d_secperunit);
YX			errors++;
YX			}
YX		if	(pp->p_offset + pp->p_size > lp->d_secperunit)
YX			{
YX			printf("partition %c: extends past end of unit %D %D %D\n",
YX			    part, pp->p_offset, pp->p_size, lp->d_secperunit);
YX			errors++;
YX			}
YX		}
YX	for	(; i < MAXPARTITIONS; i++)
YX		{
YX		part = 'a' + i;
YX		pp = &lp->d_partitions[i];
YX		if	(pp->p_size || pp->p_offset)
YX			Warning("unused partition %c: size %D offset %D",
YX			    'a' + i, pp->p_size, pp->p_offset);
YX		}
YX	return(errors);
YX	}
YX
YX/*VARARGS1*/
YXWarning(fmt, a1, a2, a3, a4, a5)
YX	char *fmt;
YX	{
YX
YX	printf("Warning, ");
YX	printf(fmt, a1, a2, a3, a4, a5);
YX	printf("\n");
YX	}
YSHAR_EOF
Yfi
Yexit 0
Y#	End of shell archive
SHAR_EOF
fi
if test -f 'pdpstand.patch'
then
	echo shar: "will not over-write existing file 'pdpstand.patch'"
else
sed 's/^Y//' << \SHAR_EOF > 'pdpstand.patch'
Y*** /usr/src/sys/pdpstand/M.s.old	Sat Jul  4 00:03:21 1992
Y--- /usr/src/sys/pdpstand/M.s	Mon Jun  5 20:26:53 1995
Y***************
Y*** 1,6 ****
Y  /
Y  /	SCCS id	@(#)M.s	1.7 (Berkeley)	7/11/83
Y! /		@(#)M.s	3.0 (2.11BSD)	7/03/92 (sms@wlv.iipo.gtegsc.com)
Y  /
Y  / Startup code for two-stage bootstrap with support for autoboot.
Y  / Supports 11/45, 11/70, 11/53, 11/73, 11/83, 11/84, 11/93, 11/94
Y--- 1,6 ----
Y  /
Y  /	SCCS id	@(#)M.s	1.7 (Berkeley)	7/11/83
Y! /		@(#)M.s	3.1 (2.11BSD)	1995/06/01 (sms@wlv.iipo.gtegsc.com)
Y  /
Y  / Startup code for two-stage bootstrap with support for autoboot.
Y  / Supports 11/45, 11/70, 11/53, 11/73, 11/83, 11/84, 11/93, 11/94
Y***************
Y*** 37,45 ****
Y  / 192K and therefore overwrites boot here.  Just change the .=400^.
Y  / below to something like .=10240^.  This will move the critical
Y  / sections of boot up far enough so that the load can finish.
Y! / We can't actually load boot higher than 192K since it has to be
Y! / loaded on a 64K boundry and it can't use memory above 256-8K (so
Y! / it can run on any system).
Y  /
Y  .=400^.
Y  
Y--- 37,44 ----
Y  / 192K and therefore overwrites boot here.  Just change the .=400^.
Y  / below to something like .=10240^.  This will move the critical
Y  / sections of boot up far enough so that the load can finish.
Y! / We can't actually load boot too much higher because it can't use memory
Y! / above 256-8K (to avoid UNIBUS mapping problems).
Y  /
Y  .=400^.
Y  
Y***************
Y*** 79,99 ****
Y  
Y  
Y  / Set user I space registers to physical N*64kb and I/O page.  This is
Y! / where boot will copy itself to.  Boot is very simple minded about its
Y! / I/O addressing.  To compute physical memory addresses for I/O devices,
Y! / it simply hands off an address within itself as the low word and
Y! / ``segflag'' as the high order word.  This has the immediate consequence
Y! / that boot *MUST* be located on a 64Kb boundry.
Y  /
Y! / Also, several constraints force us to keep boot in the bootom 248Kb of
Y! / memory (UNIBUS mapping being a primary contender.)  If boot is ever
Y! / fixed so that it can be located on a non-64Kb boundry this constraint
Y! / will still be present.
Y  /
Y! / All told, unless boot's method of managing its I/O addressing and
Y! / physical addressing is completely reworked, 3*64Kb is probably the
Y! / highest we'll ever see boot relocated.  This means that the maximum size
Y! / of any program boot can load is 192Kb.  That size includes text, data
Y  / and bss.
Y  
Y  N	= 3			/ 3*64Kb = 192Kb
Y--- 78,96 ----
Y  
Y  
Y  / Set user I space registers to physical N*64kb and I/O page.  This is
Y! / where boot will copy itself to.  Boot is less simple minded about its
Y! / I/O addressing than it used to be.  Physical memory addresses are now
Y! / calculated (because support was needed for running split I/D utilities)
Y! / rather than assuming that boot is loaded on a 64kb boundary. 
Y  /
Y! / The constraint forcing us to keep boot in the bottom 248Kb of
Y! / memory is UNIBUS mapping.  There would be little difficulty in relocating
Y! / Boot much higher on a Qbus system.
Y  /
Y! / Unless boot's method of managing its I/O addressing and physical addressing 
Y! / is reworked some more, 3*64Kb +/- a couple Kb is probably the highest
Y! / we'll ever relocate boot.  This means that the maximum size
Y! / of any program boot can load is ~192Kb.  That size includes text, data
Y  / and bss.
Y  
Y  N	= 3			/ 3*64Kb = 192Kb
Y***************
Y*** 178,186 ****
Y  	mov	$_end+512.,sp
Y  	mov	sp,r5
Y  
Y- 	.globl	_segflag
Y- 	mov	$N,_segflag
Y- 
Y  	jsr	pc,_main
Y  	mov	_cputype,r0
Y  	mov	_bootcsr,r1	/ csr of boot controller (from ROMs)
Y--- 175,180 ----
Y***************
Y*** 294,302 ****
Y  .globl	_clrseg
Y  _clrseg:
Y  	mov	4(sp),r0
Y- 	beq	2f
Y  	asr	r0
Y  	bic	$!77777,r0
Y  	mov	2(sp),r1
Y  1:
Y  	clr	-(sp)
Y--- 288,296 ----
Y  .globl	_clrseg
Y  _clrseg:
Y  	mov	4(sp),r0
Y  	asr	r0
Y  	bic	$!77777,r0
Y+ 	beq	2f
Y  	mov	2(sp),r1
Y  1:
Y  	clr	-(sp)
Y***************
Y*** 323,331 ****
Y  
Y  .globl	__rtt
Y  __rtt:
Y! 	halt
Y  
Y! .globl	_trap
Y  
Y  trap:
Y  	mov	*$PS,-(sp)
Y--- 317,327 ----
Y  
Y  .globl	__rtt
Y  __rtt:
Y! 	br	.		/ Can't do halt because that is an illegal
Y! 				/   instruction in 'user mode' (which Boot
Y! 				/   runs in).
Y  
Y! 	.globl	_trap
Y  
Y  trap:
Y  	mov	*$PS,-(sp)
Y***************
Y*** 365,373 ****
Y  
Y  .data
Y  .globl	_cputype
Y! .globl	_ksep, _sep_id, _ubmap
Y! .globl	_bootopts, _bootdev, _checkword, _bootcsr
Y  
Y  nofault:	.=.+2	/ where to go on predicted trap
Y  _cputype:	.=.+2	/ cpu type
Y  _sep_id:	.=.+1	/ 1 if we have separate I and D
Y--- 361,372 ----
Y  
Y  .data
Y  .globl	_cputype
Y! .globl	_ksep, _sep_id, _ubmap, _ssr3copy
Y! .globl	_bootopts, _bootdev, _checkword, _bootcsr, _bootctlr
Y  
Y+ _ssr3copy:	.=.+2	/ copy of SSR3.  Always 0 in Boot because that runs
Y+ 			/ in user mode.  The standalone utilities which run
Y+ 			/ in kernel mode have their copy of SSR3 in srt0.s
Y  nofault:	.=.+2	/ where to go on predicted trap
Y  _cputype:	.=.+2	/ cpu type
Y  _sep_id:	.=.+1	/ 1 if we have separate I and D
Y***************
Y*** 376,380 ****
Y--- 375,380 ----
Y  _bootopts:	.=.+2	/ flags if an autoboot
Y  _bootdev:	.=.+2	/ device booted from
Y  _bootcsr:	.=.+2	/ csr of device booted from
Y+ _bootctlr:	.=.+2	/ number of controller booted from
Y  _checkword:	.=.+2	/ saved r2, complement of bootopts if an autoboot
Y  j11typ:	.byte 0, 73., 83., 0, 53., 93.
Y*** /usr/src/sys/pdpstand/Makefile.old	Sat Apr  9 00:10:52 1994
Y--- /usr/src/sys/pdpstand/Makefile	Wed Jun  7 21:11:57 1995
Y***************
Y*** 1,13 ****
Y- #
Y  #	Standalone Makefile
Y  #
Y! #	Note that there are limitations on how large a program may
Y! #	be loaded along with all device drivers.  This is especially
Y! #	a problem with restor.  Programs should be <= 48K to be safe.
Y  #
Y  #	If a GENERIC kernel distribution is being created be sure
Y  #	to install /sys/pdpdist/dtab (or /etc/dtab.save) as ${ROOT}/etc/dtab 
Y  #	so that the GENERIC kernel can find the tape device.
Y  
Y  # DISK	which disk to take a root dump of for the distribution tape
Y  # TAPE	which tape to write the distribution on
Y--- 1,25 ----
Y  #	Standalone Makefile
Y  #
Y! #	The limitations on program size have been removed.  The addition
Y! #	of disklabel support pushed 'restor' over the limit.  Even with
Y! #	additional space saving measures it was impossible to fit restor
Y! #	into 48kb.  'icheck' and 'restor' are now built with split I/D.
Y  #
Y+ #	This is not as bad as it sounds - the kernel has not been able to
Y+ #	run on a non split machine for many years.  It made little sense 
Y+ #	to restrict the standalone utilities to non-split mode when the
Y+ #	operating system itself required split I/D.
Y+ #
Y+ #	It is still possible to hand craft a version of the utilities by leaving
Y+ #	out all but the necessary drivers. 
Y+ #
Y  #	If a GENERIC kernel distribution is being created be sure
Y  #	to install /sys/pdpdist/dtab (or /etc/dtab.save) as ${ROOT}/etc/dtab 
Y  #	so that the GENERIC kernel can find the tape device.
Y+ #
Y+ # 1995/06/05 - add disklabel program to Makefile.
Y+ # 1995/06/01 - use split I/D for icheck and restor.
Y+ # 1995/05/30 - Begin adding disklabel support.
Y  
Y  # DISK	which disk to take a root dump of for the distribution tape
Y  # TAPE	which tape to write the distribution on
Y***************
Y*** 23,38 ****
Y  RESTOR=	${ETCSRC}/restor/restor.c
Y  ICHECK=	${ETCSRC}/icheck.c
Y  
Y! DEFS=	-DSTANDALONE -I${ROOT}/usr/include
Y  CFLAGS=	-O ${DEFS}
Y  
Y  BOOT=	M.o boot.o ubmapset.o
Y! DRIVERS=prf.o sys.o \
Y  	ht.o tm.o ts.o tmscp.o \
Y  	xp.o rk.o rl.o br.o hk.o si.o ra.o
Y  
Y! ALL=	mtboot boot mkfs restor icheck maketape toyset
Y  
Y  .c.o:
Y  	cc ${CFLAGS} -c $*.c
Y  
Y--- 35,52 ----
Y  RESTOR=	${ETCSRC}/restor/restor.c
Y  ICHECK=	${ETCSRC}/icheck.c
Y  
Y! DEFS=	-DSTANDALONE -I${ROOT}/usr/include -I${ROOT}.
Y  CFLAGS=	-O ${DEFS}
Y  
Y  BOOT=	M.o boot.o ubmapset.o
Y! DRIVERS=prf.o sys.o label.o \
Y  	ht.o tm.o ts.o tmscp.o \
Y  	xp.o rk.o rl.o br.o hk.o si.o ra.o
Y  
Y! ALL=	mtboot boot disklabel mkfs restor icheck maketape toyset
Y  
Y+ all: ${ALL}
Y+ 
Y  .c.o:
Y  	cc ${CFLAGS} -c $*.c
Y  
Y***************
Y*** 39,45 ****
Y  .s.o:
Y  	/lib/cpp -P ${DEFS} $< | as -u -V -o $@
Y  
Y! all: ${ALL}
Y  
Y  distribution: tape1 switch_tapes tape2
Y  
Y--- 53,60 ----
Y  .s.o:
Y  	/lib/cpp -P ${DEFS} $< | as -u -V -o $@
Y  
Y! srt0-i.o: srt0.s
Y! 	/lib/cpp -P -DSPLIT_ID ${DEFS} srt0.s | as -u -V -o $@
Y  
Y  distribution: tape1 switch_tapes tape2
Y  
Y***************
Y*** 90,96 ****
Y  	ar rv $@ $?
Y  	ranlib $@
Y  
Y- 
Y  mkfs.o: ${MKFS}
Y  	cc ${CFLAGS} -c ${MKFS}
Y  
Y--- 105,110 ----
Y***************
Y*** 109,127 ****
Y  	ld -X -o $@ M.o conf.o boot.o ubmapset.o libsa.a -lc
Y  
Y  mkfs: srt0.o conf.o libsa.a mkfs.o
Y! 	ld -o $@ srt0.o conf.o $@.o libsa.a -lc
Y  
Y! restor: srt0.o conf.o libsa.a restor.o
Y! 	ld -o $@ srt0.o conf.o $@.o libsa.a -lc
Y  
Y! icheck: srt0.o conf.o libsa.a icheck.o
Y! 	ld -o $@ srt0.o conf.o $@.o libsa.a -lc
Y  
Y  maketape: maketape.c
Y  	cc -o $@ maketape.c
Y  
Y  toyset: toyset.o srt0.o conf.o libsa.a
Y! 	ld -o $@ srt0.o conf.o $@.o libsa.a -lc
Y  
Y  tags: FRC
Y  	rm -f tags
Y--- 123,144 ----
Y  	ld -X -o $@ M.o conf.o boot.o ubmapset.o libsa.a -lc
Y  
Y  mkfs: srt0.o conf.o libsa.a mkfs.o
Y! 	ld -X -o $@ srt0.o conf.o $@.o libsa.a -lc
Y  
Y! restor: srt0-i.o conf.o libsa.a restor.o
Y! 	ld -X -i -o $@ srt0-i.o conf.o $@.o libsa.a -lc
Y  
Y! icheck: srt0-i.o conf.o libsa.a icheck.o
Y! 	ld -X -i -o $@ srt0-i.o conf.o $@.o libsa.a -lc
Y  
Y+ disklabel: srt0.o conf.o libsa.a disklabel.o displaylab.o
Y+ 	ld -X -o $@ srt0.o conf.o $@.o displaylab.o libsa.a -lc
Y+ 
Y  maketape: maketape.c
Y  	cc -o $@ maketape.c
Y  
Y  toyset: toyset.o srt0.o conf.o libsa.a
Y! 	ld -X -o $@ srt0.o conf.o $@.o libsa.a -lc
Y  
Y  tags: FRC
Y  	rm -f tags
Y***************
Y*** 141,148 ****
Y--- 158,168 ----
Y  boot.o:		boot.c
Y  conf.o:		conf.c
Y  cat.o:		cat.c
Y+ displaylab.o:	displaylab.c
Y+ disklabel.o:	disklabel.c
Y  hk.o:		hk.c
Y  ht.o:		ht.c
Y+ label.o:	label.c
Y  mtboot.o:	mtboot.s
Y  prf.o:		prf.c
Y  rk.o:		rk.c
Y***************
Y*** 149,154 ****
Y--- 169,175 ----
Y  rl.o:		rl.c
Y  br.o:		br.c
Y  srt0.o:		srt0.s
Y+ srt0-i.o:	srt0.s
Y  sys.o:		sys.c
Y  tm.o:		tm.c
Y  tmscp.o:	tmscp.c
Y*** /usr/src/sys/pdpstand/boot.c.old	Sat Jan  2 00:18:13 1993
Y--- /usr/src/sys/pdpstand/boot.c	Thu Jun  8 19:31:39 1995
Y***************
Y*** 3,15 ****
Y   * All rights reserved.  The Berkeley software License Agreement
Y   * specifies the terms and conditions for redistribution.
Y   *
Y!  *	@(#)boot.c	2.2 (2.11BSD) 1/1/93
Y   */
Y  #include "../h/param.h"
Y  #include "../machine/seg.h"
Y  #include "../machine/koverlay.h"
Y- #include "../h/fs.h"
Y- #include "../h/inode.h"
Y  #include "../h/reboot.h"
Y  #include "saio.h"
Y  #include <a.out.h>
Y--- 3,13 ----
Y   * All rights reserved.  The Berkeley software License Agreement
Y   * specifies the terms and conditions for redistribution.
Y   *
Y!  *	@(#)boot.c	2.3 (2.11BSD) 1995/06/08
Y   */
Y  #include "../h/param.h"
Y  #include "../machine/seg.h"
Y  #include "../machine/koverlay.h"
Y  #include "../h/reboot.h"
Y  #include "saio.h"
Y  #include <a.out.h>
Y***************
Y*** 30,35 ****
Y--- 28,34 ----
Y  #define	SEG_OVLY	04
Y  
Y  extern	caddr_t	*bootcsr;	/* csr of boot controller */
Y+ extern	int	bootctlr;	/* boot controller number */
Y  extern	int	bootopts;	/* boot options from previous incarnation */
Y  extern	int	bootdev;	/* makedev(major,unit) booted from */
Y  extern	int	checkword;	/* one's complements of bootopts */
Y***************
Y*** 38,43 ****
Y--- 37,46 ----
Y  extern	bool_t	sep_id;		/* does the cpu support separate I/D? */
Y  extern	int	ndevsw;		/* number of devices in devsw[] */
Y  extern	char	ADJcsr[];	/* adjustments for ROM csr addresses */
Y+ extern	char	*itoa();
Y+ extern	char	*index();
Y+ extern	struct	devsw devsw[];	/* device table */
Y+ extern	struct	iob	iob[];	/* I/O descriptor table */
Y  
Y  char		module[] = "Boot"; /* this program's name (used by trap) */
Y  bool_t		overlaid = 0;
Y***************
Y*** 121,136 ****
Y  main()
Y  {
Y  	register int i, j, maj;
Y! 	int retry = 0;
Y  	caddr_t	*adjcsr;
Y  	struct loadtable *setup();
Y  	struct iob *file;
Y! 	char	line[64], defnam[64], *itoa();
Y  
Y  	maj = major(bootdev);
Y  	if (maj >= ndevsw)
Y  		_stop("bad major");		/* can't happen */
Y  	adjcsr = (caddr_t *)((short)bootcsr - ADJcsr[maj]);
Y  	for (i = 0; devsw[maj].dv_csr != (caddr_t) -1; i++) {
Y  		if (adjcsr == devsw[maj].dv_csr[i])
Y  			break;
Y--- 124,140 ----
Y  main()
Y  {
Y  	register int i, j, maj;
Y! 	int retry = 0, unit, part;
Y  	caddr_t	*adjcsr;
Y  	struct loadtable *setup();
Y  	struct iob *file;
Y! 	char	*cp, *defname = "unix", line[64], defdev[64];
Y  
Y  	maj = major(bootdev);
Y  	if (maj >= ndevsw)
Y  		_stop("bad major");		/* can't happen */
Y  	adjcsr = (caddr_t *)((short)bootcsr - ADJcsr[maj]);
Y+ 
Y  	for (i = 0; devsw[maj].dv_csr != (caddr_t) -1; i++) {
Y  		if (adjcsr == devsw[maj].dv_csr[i])
Y  			break;
Y***************
Y*** 139,155 ****
Y  			break;
Y  		}
Y  	}
Y  	if (devsw[maj].dv_csr[i] == (caddr_t *) -1)
Y  		_stop("no free csr slots");
Y  	bootdev &= ~(3 << 6);
Y  	bootdev |= (i << 6);	/* controller # to bits 6&7 */
Y! 	printf("\n%d%s from %s(%d,0,0%o)\n", cputype, module, 
Y! 		devsw[major(bootdev)].dv_name, minor(bootdev), bootcsr);
Y! 	strcpy(defnam, devsw[major(bootdev)].dv_name);
Y! 	strcat(defnam, "(");
Y! 	strcat(defnam, itoa(minor(bootdev)));
Y! 	strcat(defnam, ",0)unix");
Y! 	strcpy(line, defnam);
Y  	/*
Y  	 * The machine language will have gotten the bootopts
Y  	 * if we're an autoboot and will pass them along.
Y--- 143,169 ----
Y  			break;
Y  		}
Y  	}
Y+ 
Y  	if (devsw[maj].dv_csr[i] == (caddr_t *) -1)
Y  		_stop("no free csr slots");
Y  	bootdev &= ~(3 << 6);
Y  	bootdev |= (i << 6);	/* controller # to bits 6&7 */
Y! 	bootctlr = i;
Y! 	unit = (minor(bootdev) >> 3) & 7;
Y! 	part = minor(bootdev) & 7;
Y! 
Y! 	printf("\n%d%s from %s(%d,%d,%d) at 0%o\n", cputype, module, 
Y! 		devsw[major(bootdev)].dv_name, bootctlr, unit, part, bootcsr);
Y! 
Y! 	strcpy(defdev, devsw[major(bootdev)].dv_name);
Y! 	strcat(defdev, "(");
Y! 	strcat(defdev, itoa(bootctlr));
Y! 	strcat(defdev, ",");
Y! 	strcat(defdev, itoa(unit));
Y! 	strcat(defdev, ",");
Y! 	strcat(defdev, itoa(part));
Y! 	strcat(defdev, ")");
Y! 
Y  	/*
Y  	 * The machine language will have gotten the bootopts
Y  	 * if we're an autoboot and will pass them along.
Y***************
Y*** 162,173 ****
Y  		if (bootopts & RB_ASKNAME) {
Y  			printf(": ");
Y  			gets(line);
Y! 		} else
Y  			printf(": %s\n", line);
Y  		if (line[0] == '\0') {
Y! 			strcpy(line, defnam);
Y  			printf(": %s\n", line);
Y  		}
Y  		i = open(line, 0);
Y  		j = -1;
Y  		if (i >= 0) {
Y--- 176,201 ----
Y  		if (bootopts & RB_ASKNAME) {
Y  			printf(": ");
Y  			gets(line);
Y! 		} else {
Y! 			strcpy(line, defdev);
Y! 			strcat(line, defname);
Y  			printf(": %s\n", line);
Y+ 		}
Y  		if (line[0] == '\0') {
Y! 			strcpy(line, defdev);
Y! 			strcat(line, defname);
Y  			printf(": %s\n", line);
Y  		}
Y+ /*
Y+  * If a plain filename (/unix) is entered then prepend the default
Y+  * device, e.g. ra(0,1,0) to the filename.
Y+ */
Y+ 		cp = index(line, ')');
Y+ 		if	(!cp)
Y+ 			{
Y+ 			bcopy(line, line + strlen(defdev), strlen(line) + 1);
Y+ 			bcopy(defdev, line, strlen(defdev));
Y+ 			}
Y  		i = open(line, 0);
Y  		j = -1;
Y  		if (i >= 0) {
Y***************
Y*** 179,186 ****
Y  			bootopts = RB_SINGLE | RB_ASKNAME;
Y  	} while (j < 0);
Y  	i = file->i_ino.i_dev;
Y! 	bootdev = makedev(i, file->i_unit);
Y! 	bootcsr = devsw[i].dv_csr[(file->i_unit >> 6) & 3];
Y  	bootcsr = (caddr_t *)((short)bootcsr + ADJcsr[i]);
Y  	printf("%s: bootdev=0%o bootcsr=0%o\n", module, bootdev, bootcsr);
Y  }
Y--- 207,215 ----
Y  			bootopts = RB_SINGLE | RB_ASKNAME;
Y  	} while (j < 0);
Y  	i = file->i_ino.i_dev;
Y! 	bootdev = makedev(i, 
Y! 		((file->i_ctlr << 6) | (file->i_unit << 3) | file->i_part));
Y! 	bootcsr = devsw[i].dv_csr[file->i_ctlr];
Y  	bootcsr = (caddr_t *)((short)bootcsr + ADJcsr[i]);
Y  	printf("%s: bootdev=0%o bootcsr=0%o\n", module, bootdev, bootcsr);
Y  }
Y***************
Y*** 222,228 ****
Y  checkunix(io, lt)
Y  	struct loadtable *lt;
Y  {
Y! 	char *segname;
Y  	register int ovseg, segtype;
Y  	register unsigned seglen;
Y  	struct loadmap *lm = lt->lt_map;
Y--- 251,257 ----
Y  checkunix(io, lt)
Y  	struct loadtable *lt;
Y  {
Y! 	char *segname, *toosmall = "Base too small, %dK min\n";
Y  	register int ovseg, segtype;
Y  	register unsigned seglen;
Y  	struct loadmap *lm = lt->lt_map;
Y***************
Y*** 304,316 ****
Y  		    switch (exec.a_magic) {
Y  			case A_MAGIC5:
Y  			    if (seglen <= 8 KB) {
Y! 				printf("Base too small, 8K min\n");
Y  				return(-1);
Y  			    }
Y  			    break;
Y  			case A_MAGIC6:
Y  			    if (seglen <= 48 KB) {
Y! 				printf("Base too small, 48K min\n");
Y  				return(-1);
Y  			    }
Y  			    break;
Y--- 333,345 ----
Y  		    switch (exec.a_magic) {
Y  			case A_MAGIC5:
Y  			    if (seglen <= 8 KB) {
Y! 				printf(toosmall, 8);
Y  				return(-1);
Y  			    }
Y  			    break;
Y  			case A_MAGIC6:
Y  			    if (seglen <= 48 KB) {
Y! 				printf(toosmall, 48);
Y  				return(-1);
Y  			    }
Y  			    break;
Y***************
Y*** 375,381 ****
Y  				ovseg++;
Y  				break;
Y  			default:
Y! 				printf("copyunix: bad segment type %d\n", segtype);
Y  				seglen=0;
Y  				break;
Y  		}
Y--- 404,410 ----
Y  				ovseg++;
Y  				break;
Y  			default:
Y! 				printf("copyunix: bad seg type %d\n", segtype);
Y  				seglen=0;
Y  				break;
Y  		}
Y***************
Y*** 383,388 ****
Y--- 412,422 ----
Y  		if (!seglen)
Y  			continue;
Y  		setseg(phys);
Y+ /*
Y+  * ARGH!  Despite (or in spite of) the earlier cautions against seeking and
Y+  * tape devices here is an 'lseek' that caused problems loading split I/D
Y+  * images from tape!
Y+ */
Y  		if (exec.a_magic != A_MAGIC1)
Y  			(void) lseek(io, segoff, 0);
Y  		for (addr = 0; addr < seglen; addr += 2)
Y***************
Y*** 557,574 ****
Y  	register unsigned nclicks;
Y  {
Y  	return((unsigned)(((((long) nclicks) + ((long) 63)) >> 6)));
Y- }
Y- 
Y- char *
Y- itoa(i)
Y- 	register int i;
Y- {
Y- 	static char x[8];
Y- 	register char *cp = x+8;
Y- 
Y- 	do {
Y- 		*--cp = (i % 10) + '0';
Y- 		i /= 10;
Y- 	} while (i);
Y- 	return(cp);
Y  }
Y--- 591,594 ----
Y*** /usr/src/sys/pdpstand/br.c.old	Sat Jan  2 00:20:10 1993
Y--- /usr/src/sys/pdpstand/br.c	Thu Jun  8 19:32:49 1995
Y***************
Y*** 3,9 ****
Y   * All rights reserved.  The Berkeley software License Agreement
Y   * specifies the terms and conditions for redistribution.
Y   *
Y!  *	@(#)br.c	2.1 (2.11BSD) 1/2/93
Y   */
Y  
Y  /*
Y--- 3,9 ----
Y   * All rights reserved.  The Berkeley software License Agreement
Y   * specifies the terms and conditions for redistribution.
Y   *
Y!  *	@(#)br.c	2.2 (2.11BSD) 1995/06/08
Y   */
Y  
Y  /*
Y***************
Y*** 13,19 ****
Y   */
Y  
Y  #include "../h/param.h"
Y- #include "../h/inode.h"
Y  #include "../pdpuba/brreg.h"
Y  #include "saio.h"
Y  
Y--- 13,18 ----
Y***************
Y*** 35,44 ****
Y  {
Y  	register struct brdevice *braddr;
Y  	register int ctlr;
Y! 	int com, cn, tn, sn, unit, sectrk, trkcyl, ctr;
Y  
Y! 	unit = UNITn(io->i_unit);
Y! 	ctlr = CTLRn(io->i_unit);
Y  	braddr = BRcsr[ctlr];
Y  
Y  	/* if we haven't gotten the characteristics yet, do so now. */
Y--- 34,43 ----
Y  {
Y  	register struct brdevice *braddr;
Y  	register int ctlr;
Y! 	int com, cn, tn, sn, unit, sectrk, trkcyl, ctr, bae, lo16;
Y  
Y! 	unit = io->i_unit;
Y! 	ctlr = io->i_ctlr;
Y  	braddr = BRcsr[ctlr];
Y  
Y  	/* if we haven't gotten the characteristics yet, do so now. */
Y***************
Y*** 69,81 ****
Y  	sn = io->i_bn%(sectrk * trkcyl);
Y  	tn = sn/sectrk;
Y  	sn = sn%sectrk;
Y  	braddr->brcs.w = (unit<<8);
Y  	braddr->brda = (tn<<8) | sn;
Y  	braddr->brca = cn;
Y! 	braddr->brba = io->i_ma;
Y  	braddr->brwc = -(io->i_cc>>1);
Y! 	braddr->brae = segflag;
Y! 	com = (segflag<<4)|BR_GO;
Y  	if (func == READ)
Y  		com |= BR_RCOM;
Y  	else
Y--- 68,82 ----
Y  	sn = io->i_bn%(sectrk * trkcyl);
Y  	tn = sn/sectrk;
Y  	sn = sn%sectrk;
Y+ 
Y+ 	iomapadr(io->i_ma, &bae, &lo16);
Y  	braddr->brcs.w = (unit<<8);
Y  	braddr->brda = (tn<<8) | sn;
Y  	braddr->brca = cn;
Y! 	braddr->brba = (caddr_t)lo16;
Y  	braddr->brwc = -(io->i_cc>>1);
Y! 	braddr->brae = bae;
Y! 	com = (bae<<4)|BR_GO;
Y  	if (func == READ)
Y  		com |= BR_RCOM;
Y  	else
Y*** /usr/src/sys/pdpstand/conf.c.old	Tue Apr 23 10:39:58 1991
Y--- /usr/src/sys/pdpstand/conf.c	Thu Jun 15 20:09:14 1995
Y***************
Y*** 3,56 ****
Y   * All rights reserved.  The Berkeley software License Agreement
Y   * specifies the terms and conditions for redistribution.
Y   *
Y!  *	@(#)conf.c	2.0 (2.11BSD) 4/20/91
Y   */
Y  
Y  #include "../h/param.h"
Y- #include "../h/inode.h"
Y  #include "saio.h"
Y  
Y! devread(io)
Y! 	register struct iob *io;
Y! {
Y  
Y- 	return((*devsw[io->i_ino.i_dev].dv_strategy)(io, READ));
Y- }
Y- 
Y- devwrite(io)
Y- 	register struct iob *io;
Y- {
Y- 	return((*devsw[io->i_ino.i_dev].dv_strategy)(io, WRITE));
Y- }
Y- 
Y- devopen(io)
Y- 	register struct iob *io;
Y- {
Y- 	return((*devsw[io->i_ino.i_dev].dv_open)(io));
Y- }
Y- 
Y- devclose(io)
Y- 	register struct iob *io;
Y- {
Y- 	(*devsw[io->i_ino.i_dev].dv_close)(io);
Y- }
Y- 
Y- nullsys()
Y- {
Y- 	return(-1);
Y- }
Y- 
Y  extern	int	xpstrategy(), xpopen();
Y  extern	int	brstrategy(), bropen();
Y  extern	int	rkstrategy(), rkopen();
Y  extern	int	hkstrategy(), hkopen();
Y! extern	int	rlstrategy(), rlopen();
Y  extern	int	sistrategy(), siopen();
Y! extern	int	rastrategy(), raopen(), raclose();
Y! extern	int	tmstrategy(), tmopen(), tmclose();
Y! extern	int	htstrategy(), htopen(), htclose();
Y! extern	int	tsstrategy(), tsopen(), tsclose();
Y! extern	int	tmscpstrategy(), tmscpopen(), tmscpclose();
Y  
Y  extern	caddr_t	*XPcsr[], *BRcsr[], *RKcsr[], *HKcsr[], *RLcsr[];
Y  extern	caddr_t	*SIcsr[], *RAcsr[], *TMcsr[], *HTcsr[], *TScsr[], *TMScsr[];
Y--- 3,27 ----
Y   * All rights reserved.  The Berkeley software License Agreement
Y   * specifies the terms and conditions for redistribution.
Y   *
Y!  *	@(#)conf.c	2.3 (2.11BSD) 1995/06/15
Y   */
Y  
Y  #include "../h/param.h"
Y  #include "saio.h"
Y  
Y! 	int	nullsys();
Y  
Y  extern	int	xpstrategy(), xpopen();
Y  extern	int	brstrategy(), bropen();
Y  extern	int	rkstrategy(), rkopen();
Y  extern	int	hkstrategy(), hkopen();
Y! extern	int	rlstrategy(), rlopen(), rllabel();
Y  extern	int	sistrategy(), siopen();
Y! extern	int	rastrategy(), raopen(), raclose(), ralabel();
Y! extern	int	tmstrategy(), tmopen(), tmclose(), tmseek();
Y! extern	int	htstrategy(), htopen(), htclose(), htseek();
Y! extern	int	tsstrategy(), tsopen(), tsclose(), tsseek();
Y! extern	int	tmscpstrategy(), tmscpopen(), tmscpclose(), tmscpseek();
Y  
Y  extern	caddr_t	*XPcsr[], *BRcsr[], *RKcsr[], *HKcsr[], *RLcsr[];
Y  extern	caddr_t	*SIcsr[], *RAcsr[], *TMcsr[], *HTcsr[], *TScsr[], *TMScsr[];
Y***************
Y*** 62,80 ****
Y  
Y  struct devsw devsw[] = {
Y  	"ht",	htstrategy,	htopen,		htclose,	HTcsr, /* 0 */
Y  	"tm",	tmstrategy,	tmopen,		tmclose,	TMcsr, /* 1 */
Y  	"ts",	tsstrategy,	tsopen,		tsclose,	TScsr, /* 2 */
Y  	"ram",	nullsys,	nullsys,	nullsys,	0,     /* 3 */
Y  	"hk",	hkstrategy,	hkopen,		nullsys,	HKcsr, /* 4 */
Y  	"ra",	rastrategy,	raopen,		raclose,	RAcsr, /* 5 */
Y  	"rk",	rkstrategy,	rkopen,		nullsys,	RKcsr, /* 6 */
Y  	"rl",	rlstrategy,	rlopen,		nullsys,	RLcsr, /* 7 */
Y  	"rx",	nullsys,	nullsys,	nullsys,	0,     /* 8 */
Y  	"si",	sistrategy,	siopen,		nullsys,	SIcsr, /* 9 */
Y  	"xp",	xpstrategy,	xpopen,		nullsys,	XPcsr, /* 10 */
Y  	"br",	brstrategy,	bropen,		nullsys,	BRcsr, /* 11 */
Y  	"tms",  tmscpstrategy,	tmscpopen,	tmscpclose,	TMScsr,/* 12 */
Y! 	0,	0,		0,		0,
Y  };
Y  
Y  	int	ndevsw = (sizeof (devsw) / sizeof (devsw[0])) - 1;
Y--- 33,65 ----
Y  
Y  struct devsw devsw[] = {
Y  	"ht",	htstrategy,	htopen,		htclose,	HTcsr, /* 0 */
Y+ 	nullsys, htseek,
Y  	"tm",	tmstrategy,	tmopen,		tmclose,	TMcsr, /* 1 */
Y+ 	nullsys, tmseek,
Y  	"ts",	tsstrategy,	tsopen,		tsclose,	TScsr, /* 2 */
Y+ 	nullsys, tsseek,
Y  	"ram",	nullsys,	nullsys,	nullsys,	0,     /* 3 */
Y+ 	nullsys, nullsys,
Y  	"hk",	hkstrategy,	hkopen,		nullsys,	HKcsr, /* 4 */
Y+ 	nullsys, nullsys,
Y  	"ra",	rastrategy,	raopen,		raclose,	RAcsr, /* 5 */
Y+ 	ralabel, nullsys,
Y  	"rk",	rkstrategy,	rkopen,		nullsys,	RKcsr, /* 6 */
Y+ 	nullsys, nullsys,
Y  	"rl",	rlstrategy,	rlopen,		nullsys,	RLcsr, /* 7 */
Y+ 	rllabel, nullsys,
Y  	"rx",	nullsys,	nullsys,	nullsys,	0,     /* 8 */
Y+ 	nullsys, nullsys,
Y  	"si",	sistrategy,	siopen,		nullsys,	SIcsr, /* 9 */
Y+ 	nullsys, nullsys,
Y  	"xp",	xpstrategy,	xpopen,		nullsys,	XPcsr, /* 10 */
Y+ 	nullsys, nullsys,
Y  	"br",	brstrategy,	bropen,		nullsys,	BRcsr, /* 11 */
Y+ 	nullsys, nullsys,
Y  	"tms",  tmscpstrategy,	tmscpopen,	tmscpclose,	TMScsr,/* 12 */
Y! 	nullsys, tmscpseek,
Y! 	0,	0,		0,		0,		0,
Y! 	nullsys, nullsys,
Y  };
Y  
Y  	int	ndevsw = (sizeof (devsw) / sizeof (devsw[0])) - 1;
Y***************
Y*** 95,97 ****
Y--- 80,178 ----
Y  		4,	/* BR =11 */
Y  		0,	/* TMS = 12 */
Y  		};
Y+ 
Y+ devread(io)
Y+ 	register struct iob *io;
Y+ {
Y+ 
Y+ 	return((*devsw[io->i_ino.i_dev].dv_strategy)(io, READ));
Y+ }
Y+ 
Y+ devwrite(io)
Y+ 	register struct iob *io;
Y+ {
Y+ 	return((*devsw[io->i_ino.i_dev].dv_strategy)(io, WRITE));
Y+ }
Y+ 
Y+ devopen(io)
Y+ 	register struct iob *io;
Y+ {
Y+ 	return((*devsw[io->i_ino.i_dev].dv_open)(io));
Y+ }
Y+ 
Y+ devclose(io)
Y+ 	register struct iob *io;
Y+ {
Y+ 	(*devsw[io->i_ino.i_dev].dv_close)(io);
Y+ }
Y+ 
Y+ /*
Y+  * Call the 'seek' entry for a tape device.  Seeking only works for 1kb
Y+  * records - which is how the executables are stored - not for the dump
Y+  * or tar files on a boot tape.
Y+ */
Y+ devseek(io, space)
Y+ 	register struct iob *io;
Y+ 	int	space;
Y+ 	{
Y+ 	return((*devsw[io->i_ino.i_dev].dv_seek)(io, space));
Y+ 	}
Y+ 
Y+ devlabel(io, fnc)
Y+ 	register struct iob *io;
Y+ 	int	fnc;
Y+ 	{
Y+ 	int	(*dvlab)() = devsw[io->i_ino.i_dev].dv_label;
Y+ 	int	(*strat)() = devsw[io->i_ino.i_dev].dv_strategy;
Y+ 	register struct disklabel *lp;
Y+ 	register struct partition *pi;
Y+ 	char	*name = devsw[io->i_ino.i_dev].dv_name;
Y+ 	
Y+ 	switch	(fnc)
Y+ 		{
Y+ 		case	WRITELABEL:
Y+ 			return(writelabel(io, strat, name));
Y+ 		case	READLABEL:
Y+ 			return(readlabel(io, strat, name));
Y+ 		case	DEFAULTLABEL:
Y+ /*
Y+  * Zero out the label buffer and then assign defaults common to all drivers.
Y+  * Many of these are rarely (if ever) changed.  The 'a' partition is set up
Y+  * to be one sector past the label sector - the driver is expected to change
Y+  * this to span the volume once the size is known.
Y+ */
Y+ 			lp = &io->i_label;
Y+ 			pi = &lp->d_partitions[0];
Y+ 			bzero(lp, sizeof (struct disklabel));
Y+ 			lp->d_npartitions = 1;
Y+ 			pi->p_offset = 0;
Y+ 			pi->p_size = LABELSECTOR + 1;
Y+ 			pi->p_fsize = DEV_BSIZE;
Y+ 			pi->p_frag = 1;
Y+ 			pi->p_fstype = FS_V71K;
Y+ 			strcpy(lp->d_packname, "DEFAULT");
Y+ 			lp->d_secsize = 512;
Y+ 			lp->d_interleave = 1;
Y+ 			lp->d_rpm = 3600;
Y+ /*
Y+  * param.h declares BBSIZE to be DEV_BSIZE which is 1kb.  This is _wrong_,
Y+  * the boot block size (what the bootroms read) is 512.  The disklabel(8)
Y+  * program explicitly sets d_bbsize to 512 so we do the same thing here.
Y+  *
Y+  * What a mess - when the 1k filesystem was created there should have been
Y+  * a (clearer) distinction made between '(hardware) sectors' and 
Y+  * '(filesystem) blocks'.  Sigh.
Y+ */
Y+ 			lp->d_bbsize = 512;
Y+ 			lp->d_sbsize = SBSIZE;
Y+ 			return((*dvlab)(io));
Y+ 		default:
Y+ 			printf("devlabel: bad fnc %d\n");
Y+ 			return(-1);
Y+ 		}
Y+ 	}
Y+ 
Y+ nullsys()
Y+ {
Y+ 	return(-1);
Y+ }
Y*** /usr/src/sys/pdpstand/hk.c.old	Sun Apr 21 00:06:35 1991
Y--- /usr/src/sys/pdpstand/hk.c	Thu Jun  8 19:35:27 1995
Y***************
Y*** 3,9 ****
Y   * All rights reserved.  The Berkeley software License Agreement
Y   * specifies the terms and conditions for redistribution.
Y   *
Y!  *	@(#)hk.c	2.0 (2.11BSD) 4/20/91
Y   */
Y  
Y  /*
Y--- 3,9 ----
Y   * All rights reserved.  The Berkeley software License Agreement
Y   * specifies the terms and conditions for redistribution.
Y   *
Y!  *	@(#)hk.c	2.1 (2.11BSD) 1995/06/08
Y   */
Y  
Y  /*
Y***************
Y*** 11,17 ****
Y   */
Y  
Y  #include "../h/param.h"
Y- #include "../h/inode.h"
Y  #include "../pdpuba/hkreg.h"
Y  #include "saio.h"
Y  
Y--- 11,16 ----
Y***************
Y*** 35,44 ****
Y  	register unit, com;
Y  	register struct hkdevice *hkaddr;
Y  	daddr_t bn;
Y! 	int sn, cn, tn, ctlr;
Y  
Y! 	unit = UNITn(io->i_unit);
Y! 	ctlr = CTLRn(io->i_unit);
Y  	hkaddr = HKcsr[ctlr];
Y  	if (hk_mntflg[ctlr][unit] != '1') {
Y  		hk_drvtyp[ctlr][unit] = 0;
Y--- 34,43 ----
Y  	register unit, com;
Y  	register struct hkdevice *hkaddr;
Y  	daddr_t bn;
Y! 	int sn, cn, tn, ctlr, bae, lo16;
Y  
Y! 	unit = io->i_unit;
Y! 	ctlr = io->i_ctlr;
Y  	hkaddr = HKcsr[ctlr];
Y  	if (hk_mntflg[ctlr][unit] != '1') {
Y  		hk_drvtyp[ctlr][unit] = 0;
Y***************
Y*** 70,80 ****
Y  	tn = sn/NSECT;
Y  	sn = sn%NSECT;
Y  
Y  	hkaddr->hkcyl = cn;
Y  	hkaddr->hkda = (tn<<8) | sn;
Y! 	hkaddr->hkba = io->i_ma;
Y  	hkaddr->hkwc = -(io->i_cc>>1);
Y! 	com = hk_drvtyp[ctlr][unit]|(segflag << 8) | HK_GO;
Y  	if (func == READ)
Y  		com |= HK_READ;
Y  	else if (func == WRITE)
Y--- 69,80 ----
Y  	tn = sn/NSECT;
Y  	sn = sn%NSECT;
Y  
Y+ 	iomapadr(io->i_ma, &bae, &lo16);
Y  	hkaddr->hkcyl = cn;
Y  	hkaddr->hkda = (tn<<8) | sn;
Y! 	hkaddr->hkba = (caddr_t)lo16;
Y  	hkaddr->hkwc = -(io->i_cc>>1);
Y! 	com = hk_drvtyp[ctlr][unit]|(bae << 8) | HK_GO;
Y  	if (func == READ)
Y  		com |= HK_READ;
Y  	else if (func == WRITE)
Y*** /usr/src/sys/pdpstand/ht.c.old	Sun Apr 21 00:07:30 1991
Y--- /usr/src/sys/pdpstand/ht.c	Thu Jun  8 19:35:38 1995
Y***************
Y*** 3,9 ****
Y   * All rights reserved.  The Berkeley software License Agreement
Y   * specifies the terms and conditions for redistribution.
Y   *
Y!  *	@(#)ht.c	2.0 (2.11BSD) 4/20/91
Y   */
Y  
Y  /*
Y--- 3,9 ----
Y   * All rights reserved.  The Berkeley software License Agreement
Y   * specifies the terms and conditions for redistribution.
Y   *
Y!  *	@(#)ht.c	2.2 (2.11BSD) 1995/06/08
Y   */
Y  
Y  /*
Y***************
Y*** 11,17 ****
Y   */
Y  
Y  #include "../h/param.h"
Y- #include "../h/inode.h"
Y  #include "../pdpuba/htreg.h"
Y  #include "saio.h"
Y  
Y--- 11,16 ----
Y***************
Y*** 32,51 ****
Y  	register struct iob *io;
Y  {
Y  	register skip;
Y! 	register int ctlr = CTLRn(io->i_unit);
Y! 	int i;
Y  
Y  	if (genopen(NHT, io) < 0)
Y  		return(-1);
Y  	htstrategy(io, HT_REW);
Y! 	skip = io->i_boff;
Y  	while (skip--) {
Y  		io->i_cc = -1;
Y  		while (htstrategy(io, HT_SFORW))
Y  			continue;
Y! 		i = 0;
Y! 		while (--i)
Y! 			continue;
Y  		htstrategy(io, HT_SENSE);
Y  	}
Y  	return(0);
Y--- 31,48 ----
Y  	register struct iob *io;
Y  {
Y  	register skip;
Y! 	register int ctlr = io->i_ctlr;
Y  
Y  	if (genopen(NHT, io) < 0)
Y  		return(-1);
Y+ 	io->i_flgs |= F_TAPE;
Y  	htstrategy(io, HT_REW);
Y! 	skip = io->i_part;
Y  	while (skip--) {
Y  		io->i_cc = -1;
Y  		while (htstrategy(io, HT_SFORW))
Y  			continue;
Y! 		delay(30000);
Y  		htstrategy(io, HT_SENSE);
Y  	}
Y  	return(0);
Y***************
Y*** 57,71 ****
Y  	htstrategy(io, HT_REW);
Y  }
Y  
Y  htstrategy(io, func)
Y  	register struct iob *io;
Y  {
Y  	register unit, com;
Y! 	int errcnt, ctlr;
Y  	register struct htdevice *htaddr;
Y  
Y! 	unit = UNITn(io->i_unit);
Y! 	ctlr = CTLRn(io->i_unit);
Y  	htaddr = HTcsr[ctlr];
Y  	errcnt = 0;
Y  retry:
Y--- 54,100 ----
Y  	htstrategy(io, HT_REW);
Y  }
Y  
Y+ /*
Y+  * Copy the space logic from the open routine but add the check for spacing
Y+  * backwards.
Y+ */
Y+ 
Y+ htseek(io, space)
Y+ 	struct	iob	*io;
Y+ 	register int	space;
Y+ 	{
Y+ 	register int	fnc;
Y+ 
Y+ 	if	(space < 0)
Y+ 		{
Y+ 		space = -space;
Y+ 		fnc = HT_SREV;
Y+ 		}
Y+ 	else
Y+ 		fnc = HT_SFORW;
Y+ 	while	(space--)
Y+ 		{
Y+ 		io->i_cc = -1;
Y+ 		htstrategy(io, fnc);
Y+ 		delay(30000);
Y+ 		htstrategy(io, HT_SENSE);
Y+ 		}
Y+ 	}
Y+ 
Y+ /*
Y+  * Returns 0 if no tape mark was seen.  Returns 1 if a tape mark (or error)
Y+  * has been encountered.
Y+ */
Y+ 
Y  htstrategy(io, func)
Y  	register struct iob *io;
Y  {
Y  	register unit, com;
Y! 	int errcnt, ctlr, bae, lo16;
Y  	register struct htdevice *htaddr;
Y  
Y! 	unit = io->i_unit;
Y! 	ctlr = io->i_ctlr;
Y  	htaddr = HTcsr[ctlr];
Y  	errcnt = 0;
Y  retry:
Y***************
Y*** 74,86 ****
Y  	while (htaddr->htfs & HTFS_PIP)
Y  		continue;
Y  
Y  	htaddr->httc =
Y  		((io->i_unit&H_1600BPI) ? HTTC_1600BPI : HTTC_800BPI)
Y  		| HTTC_PDP11 | unit;
Y! 	htaddr->htba = io->i_ma;
Y  	htaddr->htfc = -io->i_cc;
Y  	htaddr->htwc = -(io->i_cc >> 1);
Y! 	com = ((segflag) << 8) | HT_GO;
Y  	if (func == READ)
Y  		com |= HT_RCOM;
Y  	else if (func == WRITE)
Y--- 103,116 ----
Y  	while (htaddr->htfs & HTFS_PIP)
Y  		continue;
Y  
Y+ 	iomapadr(io->i_ma, &bae, &lo16);
Y  	htaddr->httc =
Y  		((io->i_unit&H_1600BPI) ? HTTC_1600BPI : HTTC_800BPI)
Y  		| HTTC_PDP11 | unit;
Y! 	htaddr->htba = (caddr_t) lo16;
Y  	htaddr->htfc = -io->i_cc;
Y  	htaddr->htwc = -(io->i_cc >> 1);
Y! 	com = (bae << 8) | HT_GO;
Y  	if (func == READ)
Y  		com |= HT_RCOM;
Y  	else if (func == WRITE)
Y***************
Y*** 101,107 ****
Y  	}
Y  	if (htaddr->htcs1 & HT_TRE) {
Y  		if (errcnt == 0)
Y! 			printf("\nHT%d,%d err: cs2=%o, er=%o",
Y  			    ctlr, unit, htaddr->htcs2, htaddr->hter);
Y  		htinit(htaddr);
Y  		if (errcnt++ == 10) {
Y--- 131,137 ----
Y  	}
Y  	if (htaddr->htcs1 & HT_TRE) {
Y  		if (errcnt == 0)
Y! 			printf("\nht%d,%d err: cs2=%o, er=%o",
Y  			    ctlr, unit, htaddr->htcs2, htaddr->hter);
Y  		htinit(htaddr);
Y  		if (errcnt++ == 10) {
Y*** /usr/src/sys/pdpstand/maketape.data.old	Sun Apr 28 17:01:04 1991
Y--- /usr/src/sys/pdpstand/maketape.data	Mon Jun 12 19:27:35 1995
Y***************
Y*** 2,7 ****
Y--- 2,9 ----
Y  mtboot 1
Y  boot 1
Y  * 1
Y+ disklabel 2
Y+ * 1
Y  mkfs 2
Y  * 1
Y  restor 2
Y*** /usr/src/sys/pdpstand/mtboot.s.old	Fri May  3 23:55:21 1991
Y--- /usr/src/sys/pdpstand/mtboot.s	Wed May 31 19:54:10 1995
Y***************
Y*** 1,6 ****
Y--- 1,8 ----
Y  /*
Y   * Primary tape boot program to load and execute secondary boot.
Y   *
Y+  * 1995/05/31 - unit number changed to be in bits 3-5 of 'bootdev'
Y+  *
Y   * This is a universal tape boot which can handle HT, TM, TS and TMSCP
Y   * tapes.  This boot is FULL.  Some of the more extended error
Y   * checking had to be left out to get all the drivers to fit.
Y***************
Y*** 100,105 ****
Y--- 102,108 ----
Y  	blo	1b
Y  	mov	csr,r1			/ put things where 'boot'
Y  	mov	unit,r3			/  expects them
Y+ 	ash	$3,r3			/ unit # in bits 3-5
Y  	bis	major,r3		/ the major device to high byte
Y  	clr	pc			/ go to location 0 ... no return
Y  
Y*** /usr/src/sys/pdpstand/prf.c.old	Sun Apr 21 00:13:07 1991
Y--- /usr/src/sys/pdpstand/prf.c	Sun Jun  4 12:02:42 1995
Y***************
Y*** 3,9 ****
Y   * All rights reserved.  The Berkeley software License Agreement
Y   * specifies the terms and conditions for redistribution.
Y   *
Y!  *	@(#)prf.c	1.2 (2.11BSD) 4/20/91
Y   */
Y  
Y  #include "../machine/cons.h"
Y--- 3,9 ----
Y   * All rights reserved.  The Berkeley software License Agreement
Y   * specifies the terms and conditions for redistribution.
Y   *
Y!  *	@(#)prf.c	1.3 (2.11BSD) 1995/06/04
Y   */
Y  
Y  #include "../machine/cons.h"
Y***************
Y*** 95,104 ****
Y  	KLADDR->dlxbuf = c;
Y  	if (c == '\n') {
Y  		putchar('\r');
Y- 		putchar(0177);
Y- 		putchar(0177);
Y- 		putchar(0177);
Y- 		putchar(0177);
Y  		putchar(0177);
Y  	}
Y  	putchar(0);
Y--- 95,100 ----
Y*** /usr/src/sys/pdpstand/ra.c.old	Sat Jan  2 00:29:55 1993
Y--- /usr/src/sys/pdpstand/ra.c	Mon Jul 10 21:56:45 1995
Y***************
Y*** 3,9 ****
Y   * All rights reserved.  The Berkeley software License Agreement
Y   * specifies the terms and conditions for redistribution.
Y   *
Y!  *	@(#)ra.c	2.3 (2.11BSD GTE) 1/1/93
Y   */
Y  
Y  /*
Y--- 3,9 ----
Y   * All rights reserved.  The Berkeley software License Agreement
Y   * specifies the terms and conditions for redistribution.
Y   *
Y!  *	@(#)ra.c	2.5 (2.11BSD GTE) 1995/07/10
Y   */
Y  
Y  /*
Y***************
Y*** 10,16 ****
Y   * MSCP disk device driver (rx23, rx33, rx50, rd??, ra??, rz??)
Y   */
Y  #include "../h/param.h"
Y- #include "../h/inode.h"
Y  #include "../machine/mscp.h"
Y  #include "../pdpuba/rareg.h"
Y  #include "saio.h"
Y--- 10,15 ----
Y***************
Y*** 52,57 ****
Y--- 51,66 ----
Y  } rd[NRA];
Y  
Y  static	u_char 	rainit[NRA];
Y+ static	int	mx();
Y+ 
Y+ extern	char	*itoa();
Y+ 
Y+ /*
Y+  * This contains the volume size in sectors of units which have been
Y+  * brought online.  This value is used at default label generation time
Y+  * along with the results of a 'get unit status' command to compute the
Y+  * "geometry" of the drive.
Y+ */
Y  static	long	raonline[NRA][8];
Y  
Y  raopen(io)
Y***************
Y*** 59,69 ****
Y  {
Y  	register struct radevice *raaddr;
Y  	register struct ra *racom;
Y! 	int i, ctlr, unit;
Y  
Y! 	ctlr = CTLRn(io->i_unit);
Y! 	unit = UNITn(io->i_unit);
Y! 	if (genopen(NRA, io) < 0)
Y  		return(-1);
Y  	raaddr = RAcsr[ctlr];
Y  	racom = &rd[ctlr];
Y--- 68,79 ----
Y  {
Y  	register struct radevice *raaddr;
Y  	register struct ra *racom;
Y! 	struct 	disklabel *lp = &io->i_label;
Y! 	int i, ctlr, unit, bae, lo16;
Y  
Y! 	ctlr = io->i_ctlr;
Y! 	unit = io->i_unit;
Y! 	if	(genopen(NRA, io) < 0)
Y  		return(-1);
Y  	raaddr = RAcsr[ctlr];
Y  	racom = &rd[ctlr];
Y***************
Y*** 75,94 ****
Y  		raaddr->rasa = RA_ERR | (0154/4);
Y  		if	(ra_step(raaddr, RA_STEP2, 2))
Y  			goto again;
Y! 		raaddr->rasa = (short)&racom->ra_ca.ca_ringbase;
Y  		if	(ra_step(raaddr, RA_STEP3, 3))
Y  			goto again;
Y! 		raaddr->rasa = segflag;
Y  		if	(ra_step(raaddr, RA_STEP4, 4))
Y  			goto again;
Y  		raaddr->rasa = RA_GO;
Y! 		racom->ra_ca.ca_rspl = (short)&racom->ra_rsp.m_cmdref;
Y! 		racom->ra_ca.ca_rsph = segflag;
Y! 		racom->ra_ca.ca_cmdl = (short)&racom->ra_cmd.m_cmdref;
Y! 		racom->ra_ca.ca_cmdh = segflag;
Y! 		racom->ra_cmd.m_cntflgs = 0;
Y! 		if (racmd(M_O_STCON, io->i_unit) < 0) {
Y! 			printf("RA%d STCON err\n", ctlr);
Y  			return(-1);
Y  		}
Y  		rainit[ctlr] = 1;
Y--- 85,100 ----
Y  		raaddr->rasa = RA_ERR | (0154/4);
Y  		if	(ra_step(raaddr, RA_STEP2, 2))
Y  			goto again;
Y! 		iomapadr(&racom->ra_ca.ca_ringbase, &bae, &lo16);
Y! 		raaddr->rasa = lo16;
Y  		if	(ra_step(raaddr, RA_STEP3, 3))
Y  			goto again;
Y! 		raaddr->rasa = bae;
Y  		if	(ra_step(raaddr, RA_STEP4, 4))
Y  			goto again;
Y  		raaddr->rasa = RA_GO;
Y! 		if (racmd(M_O_STCON, io) < 0) {
Y! 			printf("ra%d STCON err\n", ctlr);
Y  			return(-1);
Y  		}
Y  		rainit[ctlr] = 1;
Y***************
Y*** 97,102 ****
Y--- 103,118 ----
Y  	if (raonline[ctlr][unit] == 0)
Y  		if (ramount(io) == -1)
Y  			return(-1);
Y+ 	if	(devlabel(io, READLABEL) == -1)
Y+ 		return(-1);
Y+ 	if	(io->i_part >= lp->d_npartitions ||
Y+ 		 lp->d_partitions[io->i_part].p_size == 0)
Y+ 		{
Y+ 		printf("ra%d,%d%c bad partition # or size = 0\n",
Y+ 			ctlr, unit, 'a' + io->i_part);
Y+ 		return(-1);
Y+ 		}
Y+ 	io->i_boff = lp->d_partitions[io->i_part].p_offset;
Y  	return(0);
Y  }
Y  
Y***************
Y*** 103,109 ****
Y  raclose(io)
Y  	register struct iob *io;
Y  {
Y! 	raonline[CTLRn(io->i_unit)][UNITn(io->i_unit)] = 0;
Y  	return(0);
Y  }
Y  
Y--- 119,125 ----
Y  raclose(io)
Y  	register struct iob *io;
Y  {
Y! 	raonline[io->i_ctlr][io->i_unit] = 0;
Y  	return(0);
Y  }
Y  
Y***************
Y*** 110,120 ****
Y  ramount(io)
Y  	register struct iob *io;
Y  {
Y! 	register int ctlr = CTLRn(io->i_unit);
Y! 	register int unit = UNITn(io->i_unit);
Y  
Y! 	if (racmd(M_O_ONLIN, io->i_unit) < 0) {
Y! 		printf("RA%d: online err\n", io->i_unit);
Y  		return(-1);
Y  	}
Y  	raonline[ctlr][unit] = rd[ctlr].ra_rsp.m_uslow +  
Y--- 126,136 ----
Y  ramount(io)
Y  	register struct iob *io;
Y  {
Y! 	register int ctlr = io->i_ctlr;
Y! 	register int unit = io->i_unit;
Y  
Y! 	if (racmd(M_O_ONLIN, io) < 0) {
Y! 		printf("ra%d,%d: !online\n", ctlr, unit);
Y  		return(-1);
Y  	}
Y  	raonline[ctlr][unit] = rd[ctlr].ra_rsp.m_uslow +  
Y***************
Y*** 122,143 ****
Y  	return(0);
Y  }
Y  
Y! racmd(op, unit)
Y! 	int op, unit;
Y  {
Y  	register struct mscp *mp;
Y! 	register int ctlr = CTLRn(unit);
Y  	register struct ra *racom = &rd[ctlr];
Y  	struct	radevice *csr = RAcsr[ctlr];
Y! 	int i;
Y  
Y  	racom->ra_cmd.m_opcode = op;
Y! 	racom->ra_cmd.m_unit = UNITn(unit);
Y  	racom->ra_rsp.m_header.ra_msglen = sizeof(struct mscp);
Y  	racom->ra_cmd.m_header.ra_msglen = sizeof(struct mscp);
Y! 	racom->ra_ca.ca_rsph = RA_OWN | segflag;
Y! 	racom->ra_ca.ca_cmdh = RA_OWN | segflag;
Y  	i = csr->raip;
Y  	mp = &racom->ra_rsp;
Y  	while (1) {
Y  		while	(racom->ra_ca.ca_cmdh & RA_OWN) {
Y--- 138,170 ----
Y  	return(0);
Y  }
Y  
Y! racmd(op, io)
Y! 	int op;
Y! 	struct iob *io;
Y  {
Y  	register struct mscp *mp;
Y! 	int ctlr = io->i_ctlr;
Y! 	int unit = io->i_unit;
Y  	register struct ra *racom = &rd[ctlr];
Y  	struct	radevice *csr = RAcsr[ctlr];
Y! 	int i, bae, lo16;
Y  
Y  	racom->ra_cmd.m_opcode = op;
Y! 	racom->ra_cmd.m_unit = unit;
Y! 	racom->ra_cmd.m_cntflgs = 0;
Y  	racom->ra_rsp.m_header.ra_msglen = sizeof(struct mscp);
Y  	racom->ra_cmd.m_header.ra_msglen = sizeof(struct mscp);
Y! 
Y! 	iomapadr(&racom->ra_rsp.m_cmdref, &bae, &lo16);
Y! 	racom->ra_ca.ca_rspl = lo16;
Y! 	racom->ra_ca.ca_rsph = RA_OWN | bae;
Y! 
Y! 	iomapadr(&racom->ra_cmd.m_cmdref, &bae, &lo16);
Y! 	racom->ra_ca.ca_cmdl = lo16;
Y! 	racom->ra_ca.ca_cmdh = RA_OWN | bae;
Y! 
Y  	i = csr->raip;
Y+ 
Y  	mp = &racom->ra_rsp;
Y  	while (1) {
Y  		while	(racom->ra_ca.ca_cmdh & RA_OWN) {
Y***************
Y*** 154,191 ****
Y  		racom->ra_ca.ca_rspint = 0;
Y  		if (mp->m_opcode == (op | M_O_END))
Y  			break;
Y! 		printf("RA%d: rsp %x op %x ignored\n",
Y! 			unit,mp->m_header.ra_credits & 0xf0, mp->m_opcode);
Y  		racom->ra_ca.ca_rsph |= RA_OWN;
Y  	}
Y  	if ((mp->m_status & M_S_MASK) != M_S_SUCC) {
Y! 		printf("RA%d: err op=%x sts=%x\n",unit,
Y  			mp->m_opcode, mp->m_status);
Y  		return(-1);
Y  	}
Y  	return(0);
Y  fail:
Y! 	printf("RA%d: rasa=%o\n", ctlr, csr->rasa);
Y  }
Y  
Y  rastrategy(io, func)
Y  	register struct iob *io;
Y  {
Y  	register struct mscp *mp;
Y  	struct ra *racom;
Y! 	register int ctlr = CTLRn(io->i_unit);
Y  
Y! 	if (io->i_bn >= raonline[ctlr][UNITn(io->i_unit)])
Y! 		return(0);
Y! 
Y! 	racom = &rd[ctlr];
Y  	mp = &racom->ra_cmd;
Y  	mp->m_lbn_l = loint(io->i_bn);
Y  	mp->m_lbn_h = hiint(io->i_bn);
Y  	mp->m_bytecnt = io->i_cc;
Y! 	mp->m_buf_l = (ushort)io->i_ma;
Y! 	mp->m_buf_h = segflag;
Y! 	if (racmd(func == READ ? M_O_READ : M_O_WRITE, io->i_unit) < 0)
Y  		return(-1);
Y  	return(io->i_cc);
Y  }
Y--- 181,217 ----
Y  		racom->ra_ca.ca_rspint = 0;
Y  		if (mp->m_opcode == (op | M_O_END))
Y  			break;
Y! 		printf("ra%d: rsp %x op %x ignored\n",
Y! 			ctlr,mp->m_header.ra_credits & 0xf0, mp->m_opcode);
Y  		racom->ra_ca.ca_rsph |= RA_OWN;
Y  	}
Y  	if ((mp->m_status & M_S_MASK) != M_S_SUCC) {
Y! 		printf("ra%d,%d: err op=%x sts=%x\n", ctlr, unit,
Y  			mp->m_opcode, mp->m_status);
Y  		return(-1);
Y  	}
Y  	return(0);
Y  fail:
Y! 	printf("ra%d: rasa=%o\n", ctlr, csr->rasa);
Y  }
Y  
Y  rastrategy(io, func)
Y  	register struct iob *io;
Y+ 	int func;
Y  {
Y  	register struct mscp *mp;
Y  	struct ra *racom;
Y! 	int	bae, lo16;
Y  
Y! 	racom = &rd[io->i_ctlr];
Y  	mp = &racom->ra_cmd;
Y+ 	iomapadr(io->i_ma, &bae, &lo16);
Y  	mp->m_lbn_l = loint(io->i_bn);
Y  	mp->m_lbn_h = hiint(io->i_bn);
Y  	mp->m_bytecnt = io->i_cc;
Y! 	mp->m_buf_l = lo16;
Y! 	mp->m_buf_h = bae;
Y! 	if	(racmd(func == READ ? M_O_READ : M_O_WRITE, io) < 0)
Y  		return(-1);
Y  	return(io->i_cc);
Y  }
Y***************
Y*** 200,206 ****
Y  		{
Y  		delay(2000);
Y  		cnt++;
Y! 		if	(cnt < 10000)
Y  			continue;
Y  		printf("RA(%o) failed step %d. retrying\n",csr,step);
Y  		return(1);
Y--- 226,232 ----
Y  		{
Y  		delay(2000);
Y  		cnt++;
Y! 		if	(cnt < 5000)
Y  			continue;
Y  		printf("RA(%o) failed step %d. retrying\n",csr,step);
Y  		return(1);
Y***************
Y*** 208,217 ****
Y  	return(0);
Y  	}
Y  
Y! delay(l)
Y! 	int	l;
Y  	{
Y  
Y! 	while	(l > 0)
Y! 		l--;
Y  	}
Y--- 234,311 ----
Y  	return(0);
Y  	}
Y  
Y! /*
Y!  * This routine is called by the general 'devlabel' routine out of conf.c
Y!  * and is used by the standalone disklabel program to initialize the
Y!  * default disklabel.  The MSCP driver does not need geometry info but
Y!  * it is almost trivial (because the drive has already been brought online by
Y!  * 'raopen') to fetch the required information with a 'get unit status' 
Y!  * command.
Y! */
Y! 
Y! ralabel(io)
Y! 	struct	iob	*io;
Y  	{
Y+ 	register struct disklabel *lp = &io->i_label;
Y+ 	register char *cp, *dp;
Y+ 	daddr_t	nblks = raonline[io->i_ctlr][io->i_unit];
Y+ 	struct	mscp *mp = &rd[io->i_ctlr].ra_rsp;
Y+ 	int	nameid, numid;
Y  
Y! 	lp->d_type = DTYPE_MSCP;
Y! 	lp->d_partitions[0].p_size = nblks;  /* span the drive with 'a' */
Y! /*	lp->d_secperunit = nblks;	     /* size of entire volume */
Y! 
Y! 	if	(racmd(M_O_GTUNT, io) != 0)
Y! 		{
Y! 		printf("ra%d,%d M_OP_GTUNT failed\n", io->i_ctlr, io->i_unit);
Y! 		return(-1);
Y! 		}
Y! /*
Y!  * Yes it's a lot of code but since the standalone utilities (at least 'restor')
Y!  * are likely going to end up split I/D anyhow why not get the information.
Y!  *
Y!  * sectors/track
Y!  * tracks/group * group/cyl = tracks/cyl
Y!  * sectors/track * tracks/cyl = sectors/cyl
Y!  * sectors / sectors/cyl = cyl
Y! */
Y! 	lp->d_nsectors = mp->m_track;
Y! 	lp->d_ntracks = mp->m_group * mp->m_cylinder;
Y! 	lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks;
Y! 	lp->d_ncylinders = nblks / lp->d_secpercyl;
Y! 	nameid = (((loint(mp->m_mediaid) & 0x3f) << 9) |
Y! 		  ((hiint(mp->m_mediaid) >> 7) & 0x1ff));
Y! 	numid = hiint(mp->m_mediaid) & 0x7f;
Y! /*
Y!  * Next put 'RA81' or 'RD54', etc into the typename field.
Y! */
Y! 	cp = lp->d_typename;
Y! 	*cp++ = mx(nameid, 2);
Y! 	*cp++ = mx(nameid, 1);
Y! 	dp = itoa(numid);
Y! 	while	(*cp++ = *dp++)
Y! 		;
Y! 	*cp = mx(nameid, 0);
Y! 	if	(*cp != ' ')
Y! 		cp++;
Y! 	*cp = '\0';
Y! 	return(0);
Y! 	}
Y! 
Y! /*
Y!  * this is a routine rather than a macro to save space - shifting, etc 
Y!  * generates a lot of code.
Y! */
Y! 
Y! static
Y! mx(l, i)
Y! 	int l, i;
Y! 	{
Y! 	register int c;
Y! 
Y! 	c = (l >> (5 * i)) & 0x1f;
Y! 	if	(c == 0)
Y! 		c = ' ' - '@';
Y! 	return(c + '@');
Y  	}
Y*** /usr/src/sys/pdpstand/rk.c.old	Sun Apr 21 00:14:35 1991
Y--- /usr/src/sys/pdpstand/rk.c	Thu Jun  8 19:36:31 1995
Y***************
Y*** 3,9 ****
Y   * All rights reserved.  The Berkeley software License Agreement
Y   * specifies the terms and conditions for redistribution.
Y   *
Y!  *	@(#)rk.c	2.0 (2.11BSD) 4/20/91
Y   */
Y  
Y  /*
Y--- 3,9 ----
Y   * All rights reserved.  The Berkeley software License Agreement
Y   * specifies the terms and conditions for redistribution.
Y   *
Y!  *	@(#)rk.c	2.1 (2.11BSD) 1995/06/08
Y   */
Y  
Y  /*
Y***************
Y*** 11,17 ****
Y   */
Y  
Y  #include "../h/param.h"
Y- #include "../h/inode.h"
Y  #include "../pdpuba/rkreg.h"
Y  #include "saio.h"
Y  
Y--- 11,16 ----
Y***************
Y*** 30,46 ****
Y  	register com;
Y  	register struct rkdevice *rkaddr;
Y  	daddr_t bn;
Y! 	int dn, cn, sn;
Y  
Y  	bn = io->i_bn;
Y! 	dn = UNITn(io->i_unit);
Y  	cn = bn/12;
Y  	sn = bn%12;
Y! 	rkaddr = RKcsr[CTLRn(io->i_unit)];
Y  	rkaddr->rkda = (dn<<13) | (cn<<4) | sn;
Y! 	rkaddr->rkba = io->i_ma;
Y  	rkaddr->rkwc = -(io->i_cc>>1);
Y! 	com = (segflag<<4)|RKCS_GO;
Y  	if (func == READ)
Y  		com |= RKCS_RCOM;
Y  	else
Y--- 29,46 ----
Y  	register com;
Y  	register struct rkdevice *rkaddr;
Y  	daddr_t bn;
Y! 	int dn, cn, sn, bae, lo16;
Y  
Y  	bn = io->i_bn;
Y! 	dn = io->i_unit;
Y  	cn = bn/12;
Y  	sn = bn%12;
Y! 	iomapadr(io->i_ma, &bae, &lo16);
Y! 	rkaddr = RKcsr[io->i_ctlr];
Y  	rkaddr->rkda = (dn<<13) | (cn<<4) | sn;
Y! 	rkaddr->rkba = (caddr_t)lo16;
Y  	rkaddr->rkwc = -(io->i_cc>>1);
Y! 	com = (bae<<4)|RKCS_GO;
Y  	if (func == READ)
Y  		com |= RKCS_RCOM;
Y  	else
Y***************
Y*** 50,57 ****
Y  		continue;
Y  	if (rkaddr->rkcs<0) {	/* error bit */
Y  		printf("RK%d,%d err cy=%d sc=%d, er=%o, ds=%o\n",
Y! 		    CTLRn(io->i_unit), UNITn(io->i_unit), cn, sn,
Y! 		    rkaddr->rker, rkaddr->rkds);
Y  		return(-1);
Y  	}
Y  	return(io->i_cc);
Y--- 50,56 ----
Y  		continue;
Y  	if (rkaddr->rkcs<0) {	/* error bit */
Y  		printf("RK%d,%d err cy=%d sc=%d, er=%o, ds=%o\n",
Y! 		    io->i_ctlr, io->i_unit, cn, sn, rkaddr->rker, rkaddr->rkds);
Y  		return(-1);
Y  	}
Y  	return(io->i_cc);
Y*** /usr/src/sys/pdpstand/rl.c.old	Sat Jan  2 00:31:59 1993
Y--- /usr/src/sys/pdpstand/rl.c	Thu Jun 15 20:53:15 1995
Y***************
Y*** 3,20 ****
Y   * All rights reserved.  The Berkeley software License Agreement
Y   * specifies the terms and conditions for redistribution.
Y   *
Y!  *	@(#)rl.c	2.1 (2.11BSD) 1/2/93
Y   */
Y  
Y  /*
Y   *  RL disk driver
Y   *
Y   *	RL driver modified for the standalone shell.
Y   *	Armando P. Stettner  Digital Equipment Corp.  July, 1980
Y   */
Y  
Y  #include "../h/param.h"
Y- #include "../h/inode.h"
Y  #include "../pdpuba/rlreg.h"
Y  #include "saio.h"
Y  
Y--- 3,20 ----
Y   * All rights reserved.  The Berkeley software License Agreement
Y   * specifies the terms and conditions for redistribution.
Y   *
Y!  *	@(#)rl.c	2.3 (2.11BSD) 1995/06/15
Y   */
Y  
Y  /*
Y   *  RL disk driver
Y   *
Y+  *	Modified to handle disklabels - 1995/06/15
Y   *	RL driver modified for the standalone shell.
Y   *	Armando P. Stettner  Digital Equipment Corp.  July, 1980
Y   */
Y  
Y  #include "../h/param.h"
Y  #include "../pdpuba/rlreg.h"
Y  #include "saio.h"
Y  
Y***************
Y*** 35,41 ****
Y  struct	Rldrives
Y  {
Y  	int	cn[4];		/* location of heads for each drive */
Y! 	int	type[4];	/* parameter dependent upon drive type  (RL01/02) */
Y  	int	com;		/* read or write command word */
Y  	int	chn;		/* cylinder and head number */
Y  	unsigned int bleft;	/* bytes left to be transferred */
Y--- 35,41 ----
Y  struct	Rldrives
Y  {
Y  	int	cn[4];		/* location of heads for each drive */
Y! 	int	type[4];	/* # blocks on drive (RL01/02) */
Y  	int	com;		/* read or write command word */
Y  	int	chn;		/* cylinder and head number */
Y  	unsigned int bleft;	/* bytes left to be transferred */
Y***************
Y*** 53,124 ****
Y  	register struct iob *io;
Y  	int func;
Y  {
Y! 	int nblocks;	/* number of UNIX blocks for the drive in question */
Y! 	int drive;
Y  	int dif;
Y  	int head;
Y! 	int ctr;
Y! 	int ctlr = CTLRn(io->i_unit);
Y  	register struct rldevice *rladdr;
Y  	register struct Rldrives *rlp;
Y  
Y- 	/*
Y- 	 * We must determine what type of drive we are talking to in order 
Y- 	 * to determine how many blocks are on the device.  The rl.type[]
Y- 	 * array has been initialized with -1's so that we may test first
Y- 	 * contact with a particular drive and do this determination only once.
Y- 	 * Sorry tjk for this hack.
Y- 	 *
Y- 	 * RL02 GET STATUS BAND-AID - Fred Canter 10/14/80
Y- 	 *
Y- 	 * For some unknown reason the RL02 (seems to be
Y- 	 * only drive 1) does not return a valid drive status
Y- 	 * the first time that a GET STATUS request is issued
Y- 	 * for the drive, in fact it can take up to three or more
Y- 	 * GET STATUS requests to obtain the correct status.
Y- 	 * In order to overcome this "HACK" the driver has been
Y- 	 * modified to issue a GET STATUS request, validate the
Y- 	 * drive status returned, and then use it to determine the
Y- 	 * drive type. If a valid status is not returned after eight
Y- 	 * attempts, then an error message is printed.
Y- 	 */
Y- 	drive = UNITn(io->i_unit);
Y  	rladdr = RLcsr[ctlr];
Y  	rlp = &rl[ctlr];
Y  
Y! 	if (rlp->type[drive] < 0) {
Y! 		ctr = 0;
Y! 		do {
Y! 			/* load this register; what a dumb controller */
Y! 			rladdr->rlda = RLDA_RESET|RLDA_GS;
Y! 			/* set up csr */
Y! 			rladdr->rlcs = (drive << 8) | RL_GETSTATUS;
Y! 			while ((rladdr->rlcs & RL_CRDY) == 0)	/* wait for it */		
Y! 				continue;
Y! 		} while (((rladdr->rlmp & 0177477) != 035) && (++ctr < 8));
Y! 		if (ctr >= 8)
Y! 			printf("\nCan't get RL%d,%d sts\n", ctlr, drive);
Y! 		if (rladdr->rlmp & RLMP_DTYP) 
Y! 			rlp->type[drive] = BLKRL2;	/* drive is RL02 */
Y! 		else
Y! 			rlp->type[drive] = BLKRL1;	/* drive RL01 */
Y! 		/*
Y! 		 * When the device is first touched, find out where the heads are.
Y! 		 */
Y! 		/* find where the heads are */
Y! 		rladdr->rlcs = (drive << 8) | RL_RHDR;
Y! 		while ((rladdr->rlcs&RL_CRDY) == 0)
Y! 			continue;
Y! 		rlp->cn[drive] = ((rladdr->rlmp) >> 6) & 01777;
Y! 	}
Y! 	nblocks = rlp->type[drive];	/* how many blocks on this drive */
Y! 	if (io->i_bn >= nblocks)
Y! 		return -1;
Y  	rlp->chn = io->i_bn/20;
Y  	rlp->sn = (io->i_bn%20) << 1;
Y  	rlp->bleft = io->i_cc;
Y! 	rlp->addr.w[0] = segflag;
Y! 	rlp->addr.w[1] = (int)io->i_ma;
Y  	rlp->com = (drive << 8);
Y  	if (func == READ)
Y  		rlp->com |= RL_RCOM;
Y--- 53,75 ----
Y  	register struct iob *io;
Y  	int func;
Y  {
Y! 	int drive = io->i_unit;
Y  	int dif;
Y  	int head;
Y! 	int bae, lo16;
Y! 	int ctlr = io->i_ctlr;
Y  	register struct rldevice *rladdr;
Y  	register struct Rldrives *rlp;
Y  
Y  	rladdr = RLcsr[ctlr];
Y  	rlp = &rl[ctlr];
Y  
Y! 	iomapadr(io->i_ma, &bae, &lo16);
Y  	rlp->chn = io->i_bn/20;
Y  	rlp->sn = (io->i_bn%20) << 1;
Y  	rlp->bleft = io->i_cc;
Y! 	rlp->addr.w[0] = bae;
Y! 	rlp->addr.w[1] = lo16;
Y  	rlp->com = (drive << 8);
Y  	if (func == READ)
Y  		rlp->com |= RL_RCOM;
Y***************
Y*** 158,164 ****
Y  			while ((rladdr->rlcs & RL_CRDY) == 0)	/* wait for controller */
Y  				continue;
Y  		}
Y! 		printf("RL%d,%d err cy=%d, hd=%d, sc=%d, rlcs=%o, rlmp=%o\n",
Y  			ctlr, drive, rlp->chn>>01, rlp->chn&01, rlp->sn, 
Y  			rladdr->rlcs, rladdr->rlmp);
Y  		return(-1);
Y--- 109,115 ----
Y  			while ((rladdr->rlcs & RL_CRDY) == 0)	/* wait for controller */
Y  				continue;
Y  		}
Y! 		printf("rl%d,%d err cy=%d, hd=%d, sc=%d, rlcs=%o, rlmp=%o\n",
Y  			ctlr, drive, rlp->chn>>01, rlp->chn&01, rlp->sn, 
Y  			rladdr->rlcs, rladdr->rlmp);
Y  		return(-1);
Y***************
Y*** 165,171 ****
Y  	}
Y  	/*
Y  	 * Determine if there is more to read to satisfy this request.
Y! 	 * This is to compensate for the lacl of spiraling reads.
Y  	 */
Y  	if ((rlp->bleft -= rlp->bpart) > 0) {
Y  		rlp->addr.l += rlp->bpart;
Y--- 116,122 ----
Y  	}
Y  	/*
Y  	 * Determine if there is more to read to satisfy this request.
Y! 	 * This is to compensate for the lack of spiraling reads.
Y  	 */
Y  	if ((rlp->bleft -= rlp->bpart) > 0) {
Y  		rlp->addr.l += rlp->bpart;
Y***************
Y*** 177,183 ****
Y  }
Y  
Y  rlopen(io)
Y! 	struct iob *io;
Y! {
Y! 	return(genopen(NRL, io));
Y  }
Y--- 128,230 ----
Y  }
Y  
Y  rlopen(io)
Y! 	register struct iob *io;
Y! 	{
Y! 	register struct	disklabel *lp = &io->i_label;
Y! 	register int part = io->i_part;
Y! 
Y! 	if	(io->i_unit > 3)
Y! 		return(-1);
Y! 	if	(genopen(NRL, io) < 0)
Y! 		return(-1);
Y! 	rlgsts(io);		/* get status and head position */
Y! 	if	(devlabel(io, READLABEL) < 0)
Y! 		return(-1);
Y! 	if	(part >= lp->d_npartitions || 
Y! 		 lp->d_partitions[part].p_size == 0)
Y! 		{
Y! 		printf("rl%d,%d%c bad partition # or size = 0\n",
Y! 			io->i_ctlr, io->i_unit, 'a' + part);
Y! 		return(-1);
Y! 		}
Y! 	io->i_boff = lp->d_partitions[part].p_offset;
Y! 	return(0);
Y! 	}
Y! 
Y! /*
Y!  * We must determine what type of drive we are talking to in order 
Y!  * to determine how many blocks are on the device.  The rl.type[]
Y!  * array has been initialized with -1's so that we may test first
Y!  * contact with a particular drive and do this determination only once.
Y!  *
Y!  * RL02 GET STATUS BAND-AID - Fred Canter 10/14/80
Y!  *
Y!  * For some unknown reason the RL02 (seems to be
Y!  * only drive 1) does not return a valid drive status
Y!  * the first time that a GET STATUS request is issued
Y!  * for the drive, in fact it can take up to three or more
Y!  * GET STATUS requests to obtain the correct status.
Y!  * In order to overcome this "HACK" the driver has been
Y!  * modified to issue a GET STATUS request, validate the
Y!  * drive status returned, and then use it to determine the
Y!  * drive type. If a valid status is not returned after eight
Y!  * attempts, then an error message is printed.
Y!  */
Y! 
Y! rlgsts(io)
Y! 	struct	iob	*io;
Y! 	{
Y! 	int	ctr;
Y! 	int	drive = io->i_unit;
Y! 	int	ctlr = io->i_ctlr;
Y! 	register struct	Rldrives *rlp = &rl[ctlr];
Y! 	register struct rldevice *rladdr = RLcsr[ctlr];
Y! 
Y! 
Y! 	if (rlp->type[drive] < 0) {
Y! 		ctr = 0;
Y! 		do {
Y! 			/* load this register; what a dumb controller */
Y! 			rladdr->rlda = RLDA_RESET|RLDA_GS;
Y! 			/* set up csr */
Y! 			rladdr->rlcs = (drive << 8) | RL_GETSTATUS;
Y! 			while ((rladdr->rlcs & RL_CRDY) == 0)	/* wait for it */		
Y! 				continue;
Y! 		} while (((rladdr->rlmp & 0177477) != 035) && (++ctr < 8));
Y! 		if (ctr >= 8)
Y! 			printf("\nCan't get rl%d,%d sts\n", ctlr, drive);
Y! 		if (rladdr->rlmp & RLMP_DTYP) 
Y! 			rlp->type[drive] = BLKRL2;	/* drive is RL02 */
Y! 		else
Y! 			rlp->type[drive] = BLKRL1;	/* drive RL01 */
Y! 		/*
Y! 		 * When device is first touched, find out where the heads are.
Y! 		 */
Y! 		rladdr->rlcs = (drive << 8) | RL_RHDR;
Y! 		while ((rladdr->rlcs&RL_CRDY) == 0)
Y! 			continue;
Y! 		rlp->cn[drive] = ((rladdr->rlmp) >> 6) & 01777;
Y! 	}
Y! 	return;
Y  }
Y+ 
Y+ /*
Y+  * This generates a default label.  'rlopen' has already been called so
Y+  * we can use the 'types' field as the number of sectors on the device.
Y+ */
Y+ 
Y+ rllabel(io)
Y+ 	register struct iob *io;
Y+ 	{
Y+ 	register struct disklabel *lp = &io->i_label;
Y+ 	daddr_t	nblks = rl[io->i_ctlr].type[io->i_unit];
Y+ 
Y+ 	lp->d_type = DTYPE_DEC;
Y+ 	lp->d_partitions[0].p_size = nblks;
Y+ 	lp->d_nsectors = 20;		/* sectors per track */
Y+ 	lp->d_ntracks = 2;		/* tracks per cylinder */
Y+ 	lp->d_secpercyl = 40;		/* sectors per cylinder */
Y+ 	lp->d_ncylinders = nblks / (lp->d_nsectors * lp->d_ntracks);
Y+ 	lp->d_secperunit = nblks;
Y+ 	return(0);
Y+ 	}
Y*** /usr/src/sys/pdpstand/saio.h.old	Fri Apr 12 22:06:04 1991
Y--- /usr/src/sys/pdpstand/saio.h	Thu Jun  8 19:31:19 1995
Y***************
Y*** 3,31 ****
Y   * All rights reserved.  The Berkeley software License Agreement
Y   * specifies the terms and conditions for redistribution.
Y   *
Y!  *	@(#)saio.h	1.1 (2.10BSD Berkeley) 12/1/86
Y   */
Y  
Y  /*
Y!  * header file for standalone package
Y!  */
Y  
Y  /*
Y   * io block: includes an
Y!  * inode, cells for the use of seek, etc,
Y!  * and a buffer.
Y   */
Y  struct	iob {
Y  	char	i_flgs;
Y  	struct	inode	i_ino;
Y! 	int	i_unit;
Y  	daddr_t	i_boff;
Y- 	daddr_t	i_cyloff;
Y  	off_t	i_offset;
Y  	daddr_t	i_bn;
Y  	char	*i_ma;
Y  	int	i_cc;
Y  	char	i_buf[DEV_BSIZE];
Y  };
Y  
Y  #define	F_READ	01
Y--- 3,40 ----
Y   * All rights reserved.  The Berkeley software License Agreement
Y   * specifies the terms and conditions for redistribution.
Y   *
Y!  *	@(#)saio.h	2.1 (2.11BSD GTE) 1995/06/08
Y   */
Y  
Y  /*
Y!  * This must be done so that the standalone I/O system uses the same
Y!  * size for the inode structure as the utilities (restor, mkfs, etc).
Y!  * See the comments in mkfs.c for more information.
Y! */
Y! #undef	EXTERNALITIMES
Y  
Y+ #include <sys/fs.h>
Y+ #include <sys/inode.h>
Y+ #include <sys/disklabel.h>
Y+ 
Y  /*
Y   * io block: includes an
Y!  * inode, cells for the use of seek, etc, a buffer
Y!  * and a disklabel.
Y   */
Y  struct	iob {
Y  	char	i_flgs;
Y+ 	char	i_ctlr;
Y  	struct	inode	i_ino;
Y! 	short	i_unit;
Y! 	short	i_part;
Y  	daddr_t	i_boff;
Y  	off_t	i_offset;
Y  	daddr_t	i_bn;
Y  	char	*i_ma;
Y  	int	i_cc;
Y  	char	i_buf[DEV_BSIZE];
Y+ 	struct	disklabel i_label;
Y  };
Y  
Y  #define	F_READ	01
Y***************
Y*** 32,40 ****
Y--- 41,54 ----
Y  #define	F_WRITE	02
Y  #define	F_ALLOC	04
Y  #define	F_FILE	010
Y+ #define	F_TAPE	020
Y  #define	READ	F_READ
Y  #define	WRITE	F_WRITE
Y  
Y+ #define	READLABEL	0x1
Y+ #define	WRITELABEL	0x2
Y+ #define	DEFAULTLABEL	0x3
Y+ 
Y  /*
Y   * device switch
Y   */
Y***************
Y*** 44,71 ****
Y  	int	(*dv_open)();
Y  	int	(*dv_close)();
Y  	caddr_t	**dv_csr;
Y  };
Y  
Y- struct	devsw	devsw[];
Y- 
Y- #define	NBUFS	4
Y- 
Y- char	b[NBUFS][DEV_BSIZE];
Y- daddr_t	blknos[NBUFS];
Y- 
Y- #define	NFILES	4
Y- struct	iob	iob[NFILES];
Y- 
Y  /*
Y!  * Set to which 64Kb segment the code is physically running in.
Y!  * Must be set by the user's main (or thereabouts).
Y!  */
Y! int	segflag;
Y! 
Y! /*
Y!  * macros to extract the controller and unit number.  common to all drivers
Y!  * so the macros are defined here rather than in each driver.
Y  */
Y! 
Y! #define	CTLRn(dev)	((minor(dev) >> 6) & 3)
Y! #define	UNITn(dev)	(minor(dev) & 7)
Y--- 58,70 ----
Y  	int	(*dv_open)();
Y  	int	(*dv_close)();
Y  	caddr_t	**dv_csr;
Y+ 	int	(*dv_label)();
Y+ 	int	(*dv_seek)();
Y  };
Y  
Y  /*
Y!  * Set to inhibit 'disklabel missing or corrupt' error messages.  This
Y!  * is normally left off and only set by the standalone disklabeling utility
Y!  * when it expects to be reading an unlabeled disk.
Y  */
Y! int	Nolabelerr;
Y*** /usr/src/sys/pdpstand/si.c.old	Sat Jan  2 00:32:46 1993
Y--- /usr/src/sys/pdpstand/si.c	Thu Jun  8 19:36:51 1995
Y***************
Y*** 3,15 ****
Y   * All rights reserved.  The Berkeley software License Agreement
Y   * specifies the terms and conditions for redistribution.
Y   *
Y!  *	@(#)si.c	2.0 (2.11BSD) 4/20/91
Y   *
Y   *	SI 9500 CDC 9766 Stand Alone disk driver
Y   */
Y  
Y  #include "../h/param.h"
Y- #include "../h/inode.h"
Y  #include "../pdpuba/sireg.h"
Y  #include "saio.h"
Y  
Y--- 3,14 ----
Y   * All rights reserved.  The Berkeley software License Agreement
Y   * specifies the terms and conditions for redistribution.
Y   *
Y!  *	@(#)si.c	2.1 (2.11BSD) 1995/06/08
Y   *
Y   *	SI 9500 CDC 9766 Stand Alone disk driver
Y   */
Y  
Y  #include "../h/param.h"
Y  #include "../pdpuba/sireg.h"
Y  #include "saio.h"
Y  
Y***************
Y*** 32,43 ****
Y  sistrategy(io, func)
Y  	register struct iob *io;
Y  {
Y! 	int unit = UNITn(io->i_unit);
Y! 	register int ctlr = CTLRn(io->i_unit);
Y  	register struct sidevice *siaddr = SIcsr[ctlr];
Y  	int ii;
Y  	daddr_t bn;
Y! 	int sn, cn, tn;
Y  
Y  	/*
Y  	 * weirdness with bit 2 (04) removed - see xp.c for comments
Y--- 31,42 ----
Y  sistrategy(io, func)
Y  	register struct iob *io;
Y  {
Y! 	int unit = io->i_unit;
Y! 	register int ctlr = io->i_ctlr;
Y  	register struct sidevice *siaddr = SIcsr[ctlr];
Y  	int ii;
Y  	daddr_t bn;
Y! 	int sn, cn, tn, bae, lo16;
Y  
Y  	/*
Y  	 * weirdness with bit 2 (04) removed - see xp.c for comments
Y***************
Y*** 61,71 ****
Y  			siaddr->sicnr = SI_RESET;
Y  			siaddr->siscr = 1;
Y  		}
Y  	siaddr->sipcr = cn + (unit <<10);
Y  	siaddr->sihsr = (tn << 5) + sn;
Y! 	siaddr->simar = io->i_ma;
Y  	siaddr->siwcr = io->i_cc >> 1;
Y! 	ii = (segflag << 4) | SI_GO;
Y  	if (func == READ)
Y  		ii |= SI_READ;
Y  	else if (func == WRITE)
Y--- 60,71 ----
Y  			siaddr->sicnr = SI_RESET;
Y  			siaddr->siscr = 1;
Y  		}
Y+ 	iomapadr(io->i_ma, &bae, &lo16);
Y  	siaddr->sipcr = cn + (unit <<10);
Y  	siaddr->sihsr = (tn << 5) + sn;
Y! 	siaddr->simar = (caddr_t)lo16;
Y  	siaddr->siwcr = io->i_cc >> 1;
Y! 	ii = (bae << 4) | SI_GO;
Y  	if (func == READ)
Y  		ii |= SI_READ;
Y  	else if (func == WRITE)
Y***************
Y*** 77,83 ****
Y  		continue;
Y  
Y  	if (siaddr->sierr & SIERR_ERR) {
Y! 		printf("SI%d,%d err cy=%d hd=%d sc=%d cnr=%o, err=%o\n",
Y  			ctlr, unit, cn, tn, sn, siaddr->sicnr, siaddr->sierr);
Y  		return(-1);
Y  	}
Y--- 77,83 ----
Y  		continue;
Y  
Y  	if (siaddr->sierr & SIERR_ERR) {
Y! 		printf("si%d,%d err cy=%d hd=%d sc=%d cnr=%o, err=%o\n",
Y  			ctlr, unit, cn, tn, sn, siaddr->sicnr, siaddr->sierr);
Y  		return(-1);
Y  	}
Y*** /usr/src/sys/pdpstand/srt0.s.old	Tue Apr 23 21:29:33 1991
Y--- /usr/src/sys/pdpstand/srt0.s	Mon Jun  5 20:29:16 1995
Y***************
Y*** 1,49 ****
Y  / Startup code for standalone utilities
Y! / sms- mods to pass boot device and csr on to program
Y! / wfj- mod's to allow non sep i/d machines, error recovery
Y! /      note that the bootstrap passes the cputype through in
Y! /      r0.
Y  
Y  PS	= 177776
Y  
Y- .globl	_end
Y  .globl	_main, __rtt, _devsw, _ADJcsr
Y! .globl	_edata
Y  	jmp	start
Y  
Y  /
Y  / trap vectors
Y  /
Y! 	trap;340	/ bus error
Y! 	trap;341	/ illegal instruction
Y! 	trap;342	/ BPT
Y! 	trap;343	/ IOT
Y! 	trap;344	/ POWER FAIL
Y! 	trap;345	/ EMT
Y! tvec:
Y! 	start;346	/ TRAP
Y! .=400^.
Y! .text
Y  
Y- 
Y  start:
Y  	mov	$340,*$PS
Y! 	mov	$trap,tvec
Y! /
Y! / restore what kind of cpu we are running on
Y! 	mov	r0,*$_cputype	/ assume that the boot left this in r0
Y  	mov	r1,_bootcsr	/ assume that boot left csr in r1
Y  	mov	r3,_bootdev	/ and boot device major,minor in r3
Y  	mov	$157772,sp	/ return address,psw at 157774&6
Y- 	mov	$_edata,r0
Y- 	mov	$_end,r1
Y- 	sub	r0,r1
Y- 	inc	r1
Y- 	clc
Y- 	ror	r1
Y- 1:
Y- 	clr	(r0)+
Y- 	sob	r1,1b
Y  
Y  / controller number is in bits 6&7 of r3 (_bootdev).  major device number
Y  / is in bits 8-15.  what we need to do now is place the csr into
Y--- 1,57 ----
Y+ / 1995/06/04 - devsw[] entries are 14. bytes, need a tape seek routine entry.
Y+ / 1995/06/02 - Modifications for split I/D to work.  The vectors need to be
Y+ /	       in 'data' space.
Y+ / 1995/06/01 - Make copy of SSR3 so we can tell if split I/D is enabled.
Y+ / 1995/05/30 - devsw[] entries are 12. bytes now.
Y+ /
Y  / Startup code for standalone utilities
Y! / sms - mods to pass boot device and csr on to program
Y! /
Y! /      Note that the bootstrap passes the cputype through in r0.
Y  
Y  PS	= 177776
Y+ SSR3	= 172516
Y  
Y  .globl	_main, __rtt, _devsw, _ADJcsr
Y! 
Y! #ifdef	SPLIT_ID
Y! 	.data
Y! #else
Y! 	.text
Y! #endif
Y! ZERO:
Y  	jmp	start
Y  
Y  /
Y  / trap vectors
Y  /
Y! 	trap;340	/ 004 - bus error
Y! 	trap;341	/ 010 - illegal instruction
Y! 	trap;342	/ 014 - BPT
Y! 	trap;343	/ 020 - IOT
Y! 	trap;344	/ 024 - POWER FAIL
Y! 	trap;345	/ 030 - EMT
Y! 	start;346	/ 034 - TRAP
Y! .= ZERO + 400
Y! 	.text
Y  
Y  start:
Y  	mov	$340,*$PS
Y! 	mov	$trap,*$034
Y! 
Y! / Save information which Boot has passed thru to us
Y! 
Y! 	mov	r0,_cputype	/ assume that the boot left this in r0
Y  	mov	r1,_bootcsr	/ assume that boot left csr in r1
Y  	mov	r3,_bootdev	/ and boot device major,minor in r3
Y+ 
Y+ / Make a copy of SSR3.  If this register does not exist it is probably better
Y+ / to trap now rather than later - the absence of this register means no  split
Y+ / I/D space and the kernel won't run.
Y+ 
Y+ 	mov	*$SSR3,_ssr3copy
Y+ 
Y  	mov	$157772,sp	/ return address,psw at 157774&6
Y  
Y  / controller number is in bits 6&7 of r3 (_bootdev).  major device number
Y  / is in bits 8-15.  what we need to do now is place the csr into
Y***************
Y*** 54,62 ****
Y  	bic	$!6,r0			/ make a word index
Y  	ash	$-3,r3			/ major device # to bits 0-7
Y  	mov	r3,r2			/ save major for later
Y! 	mul	$10.,r3			/ devsw[] members are 10. bytes each
Y  	mov	_devsw+10(r3),r3	/ get csrlist for driver
Y  	add	r0,r3			/ point to controller's entry
Y  
Y  / the CSR passed from the ROMs is not necessarily the first address
Y  / of a device!  We therefore have to adjust the CSR so that the structure
Y--- 62,72 ----
Y  	bic	$!6,r0			/ make a word index
Y  	ash	$-3,r3			/ major device # to bits 0-7
Y  	mov	r3,r2			/ save major for later
Y! 	mul	$14.,r3			/ devsw[] members are 14. bytes each
Y  	mov	_devsw+10(r3),r3	/ get csrlist for driver
Y  	add	r0,r3			/ point to controller's entry
Y+ 	asr	r0			/ controller number in bits 0,1
Y+ 	mov	r0,_bootctlr		/ set default controller number
Y  
Y  / the CSR passed from the ROMs is not necessarily the first address
Y  / of a device!  We therefore have to adjust the CSR so that the structure
Y***************
Y*** 100,109 ****
Y  	mov	nofault,(sp)
Y  	rtt
Y  
Y! .data
Y! .globl	_cputype, _bootcsr, _bootdev
Y  
Y  nofault:	.=.+2	/ where to go on predicted trap
Y  _cputype:	.=.+2	/ cpu type (currently 44, 70, 73)
Y  _bootdev:	.=.+2	/ makedev(major,unit) for boot device
Y  _bootcsr:	.=.+2	/ csr of boot controller
Y--- 110,121 ----
Y  	mov	nofault,(sp)
Y  	rtt
Y  
Y! 	.data
Y! .globl	_cputype, _bootcsr, _bootdev, _ssr3copy, _bootctlr
Y  
Y  nofault:	.=.+2	/ where to go on predicted trap
Y  _cputype:	.=.+2	/ cpu type (currently 44, 70, 73)
Y  _bootdev:	.=.+2	/ makedev(major,unit) for boot device
Y  _bootcsr:	.=.+2	/ csr of boot controller
Y+ _bootctlr:	.=.+2	/ number of boot controller (bits 6 and 7 of minor)
Y+ _ssr3copy:	.=.+2	/ copy of SSR3
Y*** /usr/src/sys/pdpstand/sys.c.old	Sat Jan  2 15:01:48 1993
Y--- /usr/src/sys/pdpstand/sys.c	Mon Jun 12 21:17:02 1995
Y***************
Y*** 3,17 ****
Y   * All rights reserved.  The Berkeley software License Agreement
Y   * specifies the terms and conditions for redistribution.
Y   *
Y!  *	@(#)sys.c	2.1 (2.11BSD) 1/2/93
Y   */
Y  
Y  #include "../h/param.h"
Y- #include "../h/fs.h"
Y  #include "../h/dir.h"
Y! #include "../h/inode.h"
Y  #include "saio.h"
Y  
Y  ino_t dlook();
Y  struct direct *readdir();
Y  
Y--- 3,58 ----
Y   * All rights reserved.  The Berkeley software License Agreement
Y   * specifies the terms and conditions for redistribution.
Y   *
Y!  *	@(#)sys.c	2.2 (2.11BSD) 1995/06/08
Y   */
Y  
Y  #include "../h/param.h"
Y  #include "../h/dir.h"
Y! #include "../machine/seg.h"
Y! #include "../machine/iopage.h"
Y! #include "../machine/psl.h"
Y! #include "../machine/machparam.h"
Y  #include "saio.h"
Y  
Y+ #undef	KISA0
Y+ #define	KISA0	((u_short *) 0172340)
Y+ #define	KDSA0	((u_short *) 0172360)
Y+ 
Y+ extern	struct	devsw	devsw[];
Y+ extern	int	ssr3copy, bootctlr;
Y+ extern	long	atol();
Y+ 
Y+ /*
Y+  * These buffers are only used in mapping inode blocks to disk sectors,
Y+  * no good reason to make them global.
Y+  *
Y+  * The strange initialization is due to the fact that the 0'th case is
Y+  * not legal since it would be used for quadruple indirect files.  The
Y+  * use of the array 'b' is:
Y+  *
Y+  *	b[0] - not allocated, saving 1kb of space
Y+  *	b[1] - triple indirect block
Y+  *	b[2] - double indirect block
Y+  *	b[3] - single indirect block
Y+  *
Y+  * In the 1kb filesystem double indirect files can be up to ~65 megabytes
Y+  * (the old 512 byte filesystem double indirect files were up to ~8mb).
Y+ */
Y+ 
Y+ static	char	tplind[DEV_BSIZE], dblind[DEV_BSIZE], sngind[DEV_BSIZE];
Y+ 
Y+ static	char	*b[4] = {
Y+ 		NULL, 		/* j = 0 */
Y+ 		tplind,		/* j = 1 */
Y+ 		dblind,		/* j = 2 */
Y+ 		sngind		/* j = 3 */
Y+ 		};
Y+ 
Y+ static	daddr_t	blknos[4];
Y+ 
Y+ #define	NFILES	4
Y+ struct	iob	iob[NFILES];
Y+ 
Y  ino_t dlook();
Y  struct direct *readdir();
Y  
Y***************
Y*** 24,31 ****
Y   * wfj - mods to trap to explicitly detail why we stopped
Y   */
Y  
Y- int	segflag = 0;
Y- 
Y  static
Y  openi(n, io)
Y  	register ino_t n;
Y--- 65,70 ----
Y***************
Y*** 135,140 ****
Y--- 174,189 ----
Y  		printf("bn ovf %D\n", bn);
Y  		return((daddr_t)0);
Y  	}
Y+ /*
Y+  * At this point:
Y+  *
Y+  *  j	  NADDR-j    meaning
Y+  * ---    -------    -------
Y+  *  0       7        illegal - tossed out in the 'if' above
Y+  *  1       6        triple indirect block number
Y+  *  2       5        double indirect block number
Y+  *  3       4        single indirect block number
Y+ */
Y  
Y  	/*
Y  	 * fetch the address from the inode
Y***************
Y*** 181,196 ****
Y  	if (s==NULL || *s=='\0')
Y  		return(0);
Y  	ip = &io->i_ino;
Y! 	if ((ip->i_mode&IFMT)!=IFDIR) {
Y! 		printf("%s: not directory,mode %o ip %o\n",s, ip->i_mode, ip);
Y  		return(0);
Y  	}
Y  
Y- 	if (ip->i_size==0) {
Y- 		printf("%s: 0 len directory\n",s);
Y- 		return(0);
Y- 	}
Y- 
Y  	len = strlen(s);
Y  	dirp.loc = 0;
Y  	dirp.io = io;
Y--- 230,241 ----
Y  	if (s==NULL || *s=='\0')
Y  		return(0);
Y  	ip = &io->i_ino;
Y! 	if ((ip->i_mode&IFMT) != IFDIR || !ip->i_size) {
Y! 		printf("%s: !directory,mode %o size: %D ip %o\n", s, 
Y! 			ip->i_mode, ip->i_size, ip);
Y  		return(0);
Y  	}
Y  
Y  	len = strlen(s);
Y  	dirp.loc = 0;
Y  	dirp.io = io;
Y***************
Y*** 234,244 ****
Y--- 279,294 ----
Y  	}
Y  }
Y  
Y+ /*
Y+  * Modified to call the tape driver's seek routine.  This only works when
Y+  * the record size is DEV_BSIZE (1kb).
Y+ */
Y  lseek(fdesc, addr, ptr)
Y  	register int fdesc;
Y  	off_t addr;
Y  	int ptr;
Y  {
Y+ 	off_t	new;
Y  	register struct iob *io;
Y  
Y  	if (ptr != 0) {
Y***************
Y*** 246,255 ****
Y  		return(-1);
Y  	}
Y  	fdesc -= 3;
Y! 	if (fdesc < 0 || fdesc >= NFILES || ((io = &iob[fdesc])->i_flgs&F_ALLOC) == 0)
Y  		return(-1);
Y  	io->i_offset = addr;
Y! 	io->i_bn = fsbtodb(addr/DEV_BSIZE) + io->i_boff;
Y  	io->i_cc = 0;
Y  	return(0);
Y  }
Y--- 296,320 ----
Y  		return(-1);
Y  	}
Y  	fdesc -= 3;
Y! 	if	(fdesc < 0 || fdesc >= NFILES || 
Y! 			((io = &iob[fdesc])->i_flgs&F_ALLOC) == 0)
Y  		return(-1);
Y+ 	new = addr / DEV_BSIZE;
Y+ 
Y+ 	if	(io->i_flgs & F_TAPE)
Y+ 		{
Y+ #ifdef	debug
Y+ 		printf("seek: new=%D i_bn=%D\n", new, io->i_bn);
Y+ #endif
Y+ /*
Y+  * Subtract 1 to acccount for the block currently in the buffer - the
Y+  * tape is currently positioned at the next record.  Need to convert the 
Y+  * block number from 512 byte to 1024 byte records (undo the fsbtodb).
Y+ */
Y+ 		devseek(io, (int)(new - dbtofsb(io->i_bn) - 1));
Y+ 		}
Y  	io->i_offset = addr;
Y! 	io->i_bn = fsbtodb(new) + io->i_boff;
Y  	io->i_cc = 0;
Y  	return(0);
Y  }
Y***************
Y*** 285,301 ****
Y  #endif
Y  		tapemark = 0;
Y  		devread(io);
Y  		if (io->i_flgs&F_FILE) {
Y- 			off = io->i_offset % (off_t)DEV_BSIZE;
Y  			if (io->i_offset+(DEV_BSIZE-off) >= io->i_ino.i_size)
Y  				io->i_cc = io->i_ino.i_size - io->i_offset + off;
Y- 			io->i_cc -= off;
Y- 			if (io->i_cc <= 0)
Y- 				return(-1);
Y- 		} else {
Y- 			off = 0;
Y- 			if (tapemark)return(-1);
Y  		}
Y  		io->i_ma = &io->i_buf[off];
Y  	}
Y  	io->i_cc--;
Y--- 350,365 ----
Y  #endif
Y  		tapemark = 0;
Y  		devread(io);
Y+ 		off = io->i_offset % (off_t)DEV_BSIZE;
Y  		if (io->i_flgs&F_FILE) {
Y  			if (io->i_offset+(DEV_BSIZE-off) >= io->i_ino.i_size)
Y  				io->i_cc = io->i_ino.i_size - io->i_offset + off;
Y  		}
Y+ 		if	(tapemark)
Y+ 			return(-1);
Y+ 		io->i_cc -= off;
Y+ 		if	(io->i_cc <= 0)
Y+ 			return(-1);
Y  		io->i_ma = &io->i_buf[off];
Y  	}
Y  	io->i_cc--;
Y***************
Y*** 393,411 ****
Y  	int how;
Y  {
Y  	register char *cp;
Y! 	int i;
Y  	register struct iob *file;
Y  	register struct devsw *dp;
Y  	int fdesc;
Y- 	static first = 1;
Y- 	long atol();
Y  
Y- 	if (first) {
Y- 		for (i = 0; i < NFILES; i++)
Y- 			iob[i].i_flgs = 0;
Y- 		first = 0;
Y- 	}
Y- 
Y  	for (fdesc = 0; fdesc < NFILES; fdesc++)
Y  		if (iob[fdesc].i_flgs == 0)
Y  			goto gotfile;
Y--- 457,467 ----
Y  	int how;
Y  {
Y  	register char *cp;
Y! 	int i, i2, i3;
Y  	register struct iob *file;
Y  	register struct devsw *dp;
Y  	int fdesc;
Y  
Y  	for (fdesc = 0; fdesc < NFILES; fdesc++)
Y  		if (iob[fdesc].i_flgs == 0)
Y  			goto gotfile;
Y***************
Y*** 420,426 ****
Y  		file->i_flgs = 0;
Y  		return(-1);
Y  	}
Y! 	*cp++ = '\0';
Y  	for (dp = devsw; dp->dv_name; dp++) {
Y  		if (strcmp(str, dp->dv_name) == 0)
Y  			goto gotdev;
Y--- 476,482 ----
Y  		file->i_flgs = 0;
Y  		return(-1);
Y  	}
Y! 	*cp = '\0';
Y  	for (dp = devsw; dp->dv_name; dp++) {
Y  		if (strcmp(str, dp->dv_name) == 0)
Y  			goto gotdev;
Y***************
Y*** 429,457 ****
Y  	file->i_flgs = 0;
Y  	return(-1);
Y  gotdev:
Y! 	*(cp-1) = '(';
Y  	file->i_ino.i_dev = dp-devsw;
Y! 	for (file->i_unit = 0; *cp >= '0' && *cp <= '9'; cp++) {
Y! 		file->i_unit *= 10;
Y! 		file->i_unit += (*cp - '0');
Y  	}
Y  	if (*cp++ != ',') {
Y  badoff:
Y! 		printf("Missing offset\n");
Y  		file->i_flgs = 0;
Y  		return(-1);
Y  	}
Y! 	file->i_boff = atol(cp);
Y! 	for (;;) {
Y! 		if (*cp == ')')
Y! 			break;
Y! 		if (*cp++)
Y! 			continue;
Y  		goto badoff;
Y! 	}
Y! 	if (devopen(file) < 0)
Y  		return(-1);
Y! 	if (*++cp == '\0') {
Y  		file->i_flgs |= how+1;
Y  		goto comret;
Y  	}
Y--- 485,565 ----
Y  	file->i_flgs = 0;
Y  	return(-1);
Y  gotdev:
Y! /*
Y!  * The parse is a bit lengthier and complex now.  The syntax is now:
Y!  *
Y!  *	xx(ctlr, unit, partition)filename
Y!  * or
Y!  *	xx(unit, partition)filename
Y!  *
Y!  *
Y!  * The controller number must be less than 4.  NOTE: many drivers
Y!  * limit the number of controllers to 1 or 2.  If the controller is not 
Y!  * specified it defaults to 0.
Y!  *
Y!  * The unit number must be less than 8.
Y!  *
Y!  * The partition number is also used to specify the tapefile to be loaded.  
Y!  * When loading a tapefile the  filename' must not be specified.  The partition
Y!  * number must be less than 8.
Y! */
Y! 
Y! 	*cp++ = '(';
Y  	file->i_ino.i_dev = dp-devsw;
Y! 	for (i = 0; *cp >= '0' && *cp <= '9'; cp++) {
Y! 		i *= 10;
Y! 		i += (*cp - '0');
Y  	}
Y+ 
Y  	if (*cp++ != ',') {
Y  badoff:
Y! 		printf("Bad offset or ctlr, unit, part out of bounds\n");
Y  		file->i_flgs = 0;
Y  		return(-1);
Y  	}
Y! 
Y! 	for	(i2 = 0; *cp >= '0' && *cp <= '9'; cp++)
Y! 		{
Y! 		i2 *= 10;
Y! 		i2 += (*cp - '0');
Y! 		}
Y! /*
Y!  * If we encounter a ')' now it means we have the two arg form 'ra(x,y)'.  If
Y!  * a ',' is seen then we have the three arg form 'xp(x,y,z)'.  If neither a
Y!  * ',' or ')' it is an error.
Y! */
Y! 	if	(*cp == ')')
Y! 		{
Y! 		file->i_ctlr = bootctlr;
Y! 		file->i_unit = i;
Y! 		file->i_part = i2;
Y! 		cp++;			/* skip ) */
Y! 		}
Y! 	else if	(*cp == ',')
Y! 		{
Y! 		for	(i3 = 0, cp++; *cp >= '0' && *cp <= '9'; cp++)
Y! 			{
Y! 			i3 *= 10;
Y! 			i3 += (*cp - '0');
Y! 			}
Y! 		file->i_ctlr = i;
Y! 		file->i_unit = i2;
Y! 		file->i_part = i3;
Y! 		if	(*cp++ != ')')
Y! 			goto badoff;
Y! 		}
Y! 	else
Y  		goto badoff;
Y! 	if	(file->i_ctlr > 3 || file->i_unit > 7 || file->i_part > 7)
Y! 		goto badoff;
Y! 
Y! 	if	(devopen(file) < 0)
Y! 		{
Y! 		file->i_flgs = 0;
Y  		return(-1);
Y! 		}
Y! 	file->i_boff = 0;		/* tapes don't want this */
Y! 	if (*cp == '\0') {
Y  		file->i_flgs |= how+1;
Y  		goto comret;
Y  	}
Y***************
Y*** 542,548 ****
Y  	{
Y  	register struct devsw *dp = &devsw[io->i_ino.i_dev];
Y  	register char *cp;
Y! 	register int ctlr = CTLRn(io->i_unit);
Y  	int csr;
Y  	char line[64];
Y  
Y--- 650,656 ----
Y  	{
Y  	register struct devsw *dp = &devsw[io->i_ino.i_dev];
Y  	register char *cp;
Y! 	register int ctlr = io->i_ctlr;
Y  	int csr;
Y  	char line[64];
Y  
Y***************
Y*** 558,561 ****
Y--- 666,757 ----
Y  		return(-1);
Y  	dp->dv_csr[ctlr] = (caddr_t *)csr;
Y  	return(0);
Y+ 	}
Y+ 
Y+ delay(i)
Y+ 	int	i;
Y+ 	{
Y+ 
Y+ 	while	(i)
Y+ 		i--;
Y+ 	}
Y+ 
Y+ char *
Y+ ltoa(l)
Y+ 	u_long l;
Y+ 	{
Y+ 	static char x[12];
Y+ 	register char *cp = x + sizeof (x);
Y+ 
Y+ 	do {
Y+ 		*--cp = (l % 10) + '0';
Y+ 		l /= 10;
Y+ 	} while (l);
Y+ 	return(cp);
Y+ 	}
Y+ 
Y+ char *
Y+ itoa(i)
Y+ 	register int i;
Y+ 	{
Y+ 	static char x[8];
Y+ 	register char *cp = x + sizeof (x);
Y+ 
Y+ 	do {
Y+ 		*--cp = (i % 10) + '0';
Y+ 		i /= 10;
Y+ 	} while (i);
Y+ 	return(cp);
Y+ 	}
Y+ 
Y+ /*
Y+  * Convert a 16 bit (virtual) address into a 18 bit (UNIBUS) address.
Y+  * The address extension bits (bits 16, 17) are placed into 'bae' while
Y+  * the lower order bits (bits 0 - 15) are placed in 'lo16'.
Y+  *
Y+  * This routine was primarily created to handle split I/D kernel mode
Y+  * utilities.  Boot itself must run non split I/D and runs in user mode.
Y+  * A side effect of this routine is that Boot no longer must be loaded at
Y+  * a 64Kb boundary.
Y+  *
Y+  * Everything (Boot and standalone utilities) must still run in the low
Y+  * 248kb of memory which is mapped by the UNIBUS mapping registers.
Y+ */
Y+ 
Y+ iomapadr(buf, bae, lo16)
Y+ 	memaddr	buf;
Y+ 	u_short *bae, *lo16;
Y+ 	{
Y+ 	u_long  uadr;
Y+ 	int	curmode = *PS & PSL_CURMOD, segno;
Y+ 	u_int	nb, ts;
Y+ 	extern	char	module[];
Y+ 
Y+ 	if	(curmode == 0)
Y+ 		{		/* Kernel mode - we're in a utility */
Y+ /*
Y+  * For split I/D we need to emulate the kernel's method of looking at
Y+  * the segment registers and calculating the physical address.  Whew, forgot
Y+  * that ;-)
Y+ */
Y+ 		nb = ((int)buf >> 6) & 01777;
Y+ 		segno = nb >> 7;
Y+ 		if	(ssr3copy & 4)
Y+ 			ts = KDSA0[segno];	/* kernel I/D is on */
Y+ 		else
Y+ 			ts = KISA0[segno];	/* kernel I/D is off */
Y+ 		ts += (nb & 0177);
Y+ 		uadr = ((u_long)ts << 6) + (buf & 077);
Y+ 		}
Y+ 	else if	(curmode == PSL_CURMOD)
Y+ 		{		/* User mode - we're in Boot */
Y+ 		uadr = UISA[0];			/* No I/D for Boot! */
Y+ 		uadr <<= 6;			/* clicks to bytes */
Y+ 		uadr += buf;
Y+ 		}
Y+ 	else
Y+ 		_stop("Bad PSL mode");
Y+ 	
Y+ 	*bae = (uadr >> 16) & 3;		/* 18 bit mode */
Y+ 	*lo16 = uadr & 0xffff;
Y  	}
Y*** /usr/src/sys/pdpstand/tm.c.old	Sun Apr 21 00:19:06 1991
Y--- /usr/src/sys/pdpstand/tm.c	Thu Jun  8 19:37:33 1995
Y***************
Y*** 3,9 ****
Y   * All rights reserved.  The Berkeley software License Agreement
Y   * specifies the terms and conditions for redistribution.
Y   *
Y!  *	@(#)tm.c	2.0 (2.11BSD) 4/20/91
Y   */
Y  
Y  /*
Y--- 3,9 ----
Y   * All rights reserved.  The Berkeley software License Agreement
Y   * specifies the terms and conditions for redistribution.
Y   *
Y!  *	@(#)tm.c	2.1 (2.11BSD) 1995/06/08
Y   */
Y  
Y  /*
Y***************
Y*** 11,17 ****
Y   */
Y  
Y  #include "../h/param.h"
Y- #include "../h/inode.h"
Y  #include "../pdpuba/tmreg.h"
Y  #include "saio.h"
Y  
Y--- 11,16 ----
Y***************
Y*** 46,53 ****
Y  
Y  	if (genopen(NTM, io) < 0)
Y  		return(-1);
Y  	tmstrategy(io, TM_REW);
Y! 	skip = io->i_boff;
Y  	while (skip--) {
Y  		io->i_cc = 0;
Y  		while (tmstrategy(io, TM_SFORW))
Y--- 45,53 ----
Y  
Y  	if (genopen(NTM, io) < 0)
Y  		return(-1);
Y+ 	io->i_flgs |= F_TAPE;
Y  	tmstrategy(io, TM_REW);
Y! 	skip = io->i_part;
Y  	while (skip--) {
Y  		io->i_cc = 0;
Y  		while (tmstrategy(io, TM_SFORW))
Y***************
Y*** 61,69 ****
Y  tmstrategy(io, func)
Y  	register struct iob *io;
Y  {
Y! 	register int com, unit = UNITn(io->i_unit);
Y  	register struct tmdevice *tmaddr;
Y! 	int errcnt = 0, ctlr = CTLRn(io->i_unit);
Y  
Y  	tmaddr = TMcsr[ctlr];
Y  retry:
Y--- 61,69 ----
Y  tmstrategy(io, func)
Y  	register struct iob *io;
Y  {
Y! 	register int com, unit = io->i_unit;
Y  	register struct tmdevice *tmaddr;
Y! 	int errcnt = 0, ctlr = io->i_ctlr, bae, lo16;
Y  
Y  	tmaddr = TMcsr[ctlr];
Y  retry:
Y***************
Y*** 73,81 ****
Y  		continue;
Y  	while ((tmaddr->tmer&TMER_SDWN) != 0)
Y  		continue;
Y! 	com = (unit<<8)|(segflag<<4) | tmdens[TMDENS(unit)];
Y  	tmaddr->tmbc = -io->i_cc;
Y! 	tmaddr->tmba = io->i_ma;
Y  	if (func == READ)
Y  		tmaddr->tmcs = com | TM_RCOM | TM_GO;
Y  	else if (func == WRITE)
Y--- 73,82 ----
Y  		continue;
Y  	while ((tmaddr->tmer&TMER_SDWN) != 0)
Y  		continue;
Y! 	iomapadr(io->i_ma, &bae, &lo16);
Y! 	com = (unit<<8)|(bae<<4) | tmdens[TMDENS(unit)];
Y  	tmaddr->tmbc = -io->i_cc;
Y! 	tmaddr->tmba = (caddr_t)lo16;
Y  	if (func == READ)
Y  		tmaddr->tmcs = com | TM_RCOM | TM_GO;
Y  	else if (func == WRITE)
Y***************
Y*** 94,100 ****
Y  	}
Y  	if (tmaddr->tmer & TM_ERR) {
Y  		if (errcnt == 0)
Y! 			printf("\nTM%d,%d err: er=%o cs=%o",
Y  				ctlr, unit, tmaddr->tmer, tmaddr->tmcs);
Y  		if (errcnt++ == 10) {
Y  			printf("\n(FATAL ERROR)\n");
Y--- 95,101 ----
Y  	}
Y  	if (tmaddr->tmer & TM_ERR) {
Y  		if (errcnt == 0)
Y! 			printf("\ntm%d,%d err: er=%o cs=%o",
Y  				ctlr, unit, tmaddr->tmer, tmaddr->tmcs);
Y  		if (errcnt++ == 10) {
Y  			printf("\n(FATAL ERROR)\n");
Y***************
Y*** 105,107 ****
Y--- 106,126 ----
Y  	}
Y  	return(io->i_cc+tmaddr->tmbc);
Y  }
Y+ 
Y+ tmseek(io, space)
Y+ 	register struct iob *io;
Y+ 	int	space;
Y+ 	{
Y+ 	int	fnc;
Y+ 
Y+ 	if	(space < 0)
Y+ 		{
Y+ 		fnc = TM_SREV;
Y+ 		space = -space;
Y+ 		}
Y+ 	else
Y+ 		fnc = TM_SFORW;
Y+ 	while	(space--)
Y+ 		tmstrategy(io, fnc);
Y+ 	return(0);
Y+ 	}
Y*** /usr/src/sys/pdpstand/tmscp.c.old	Sat Jan  2 00:33:59 1993
Y--- /usr/src/sys/pdpstand/tmscp.c	Thu Jun  8 19:37:52 1995
Y***************
Y*** 1,4 ****
Y! /*	@(#)tmscp.c	7.1 (Berkeley) 6/5/86 */
Y  
Y  /****************************************************************
Y   *        Licensed from Digital Equipment Corporation           *
Y--- 1,4 ----
Y! /*	@(#)tmscp.c	7.1.2 (2.11BSD GTE) 1995/06/08 */
Y  
Y  /****************************************************************
Y   *        Licensed from Digital Equipment Corporation           *
Y***************
Y*** 30,37 ****
Y  /* ------------------------------------------------------------------------
Y   * Modification History: /sys/pdpstand/tmscp.c
Y   *
Y   * 4-20-91 sms - add multi controller and unit support (sms)
Y!  * 8-20-90 steven m. schultz (sms@wlv.imsd.contel.com)
Y   *	Port from 4.3BSD to 2.11BSD
Y   * 3-15-85  afd
Y   *	Don't ask for an interrupt when commands are issued and
Y--- 30,38 ----
Y  /* ------------------------------------------------------------------------
Y   * Modification History: /sys/pdpstand/tmscp.c
Y   *
Y+  * 5-30-95 sms - new iob structure.
Y   * 4-20-91 sms - add multi controller and unit support (sms)
Y!  * 8-20-90 steven m. schultz (sms@wlv.iipo.gtegsc.com)
Y   *	Port from 4.3BSD to 2.11BSD
Y   * 3-15-85  afd
Y   *	Don't ask for an interrupt when commands are issued and
Y***************
Y*** 43,49 ****
Y   */
Y   
Y  #include "../h/param.h"
Y- #include "../h/inode.h"
Y  #include "saio.h"
Y  
Y  /*
Y--- 44,49 ----
Y***************
Y*** 89,99 ****
Y  	register struct iob *io;
Y  {
Y  	register struct tmscpdevice *tmscpaddr;
Y! 	int ctlr = CTLRn(io->i_unit);
Y  	register struct tmscp *tms = &tmscp[ctlr];
Y   
Y  	if (genopen(NTMS, io) < 0)
Y  		return(-1);
Y  	tmscpaddr = TMScsr[ctlr];
Y  
Y  	/*
Y--- 89,101 ----
Y  	register struct iob *io;
Y  {
Y  	register struct tmscpdevice *tmscpaddr;
Y! 	int	ctlr = io->i_ctlr;
Y! 	int	unit = io->i_unit, bae, lo16;
Y  	register struct tmscp *tms = &tmscp[ctlr];
Y   
Y  	if (genopen(NTMS, io) < 0)
Y  		return(-1);
Y+ 	io->i_flgs |= F_TAPE;
Y  	tmscpaddr = TMScsr[ctlr];
Y  
Y  	/*
Y***************
Y*** 113,138 ****
Y   
Y  		while ((tmscpaddr->tmscpsa & TMSCP_STEP2) == 0)
Y  			;
Y! #		define STEP1MASK 0174377
Y! #		define STEP1GOOD (TMSCP_STEP2|TMSCP_IE|(NCMDL2<<3)|NRSPL2)
Y  		if ((tmscpaddr->tmscpsa&STEP1MASK) != STEP1GOOD)
Y  			printf(opnmsg, ctlr, 1, tmscpaddr->tmscpsa);
Y! 		tmscpaddr->tmscpsa = (short)&tms->tmscp_ca.ca_ringbase;
Y   
Y  		while ((tmscpaddr->tmscpsa & TMSCP_STEP3) == 0)
Y  			;
Y! #		define STEP2MASK 0174377
Y! #		define STEP2GOOD (TMSCP_STEP3)
Y  		if ((tmscpaddr->tmscpsa&STEP2MASK) != STEP2GOOD)
Y  			printf(opnmsg, ctlr, 2, tmscpaddr->tmscpsa);
Y! 		tmscpaddr->tmscpsa = segflag;
Y   
Y  		while ((tmscpaddr->tmscpsa & TMSCP_STEP4) == 0)
Y  			;
Y! #		define STEP3MASK 0174000
Y! #		define STEP3GOOD TMSCP_STEP4
Y  		if ((tmscpaddr->tmscpsa&STEP3MASK) != STEP3GOOD)
Y! 			printf(opnmsg, ctlr, 2, tmscpaddr->tmscpsa);
Y  		tmscpaddr->tmscpsa = TMSCP_GO;
Y  		if (tmscpcmd(ctlr, M_OP_STCON, 0) == 0)
Y  			{
Y--- 115,141 ----
Y   
Y  		while ((tmscpaddr->tmscpsa & TMSCP_STEP2) == 0)
Y  			;
Y! #define STEP1MASK 0174377
Y! #define STEP1GOOD (TMSCP_STEP2|TMSCP_IE|(NCMDL2<<3)|NRSPL2)
Y! 		iomapadr(&tms->tmscp_ca.ca_ringbase, &bae, &lo16);
Y  		if ((tmscpaddr->tmscpsa&STEP1MASK) != STEP1GOOD)
Y  			printf(opnmsg, ctlr, 1, tmscpaddr->tmscpsa);
Y! 		tmscpaddr->tmscpsa = lo16;
Y   
Y  		while ((tmscpaddr->tmscpsa & TMSCP_STEP3) == 0)
Y  			;
Y! #define STEP2MASK 0174377
Y! #define STEP2GOOD (TMSCP_STEP3)
Y  		if ((tmscpaddr->tmscpsa&STEP2MASK) != STEP2GOOD)
Y  			printf(opnmsg, ctlr, 2, tmscpaddr->tmscpsa);
Y! 		tmscpaddr->tmscpsa = bae;
Y   
Y  		while ((tmscpaddr->tmscpsa & TMSCP_STEP4) == 0)
Y  			;
Y! #define STEP3MASK 0174000
Y! #define STEP3GOOD TMSCP_STEP4
Y  		if ((tmscpaddr->tmscpsa&STEP3MASK) != STEP3GOOD)
Y! 			printf(opnmsg, ctlr, 3, tmscpaddr->tmscpsa);
Y  		tmscpaddr->tmscpsa = TMSCP_GO;
Y  		if (tmscpcmd(ctlr, M_OP_STCON, 0) == 0)
Y  			{
Y***************
Y*** 141,170 ****
Y  			}
Y  		tmsoffline[ctlr] = 0;
Y  		}
Y! 	tms->tmscp_cmd.mscp_unit = UNITn(io->i_unit);
Y  	/* 
Y  	 * Has this unit been issued an ONLIN?
Y  	 */
Y! 	if (tms_offline[ctlr][tms->tmscp_cmd.mscp_unit])
Y  		{
Y  		if (tmscpcmd(ctlr, M_OP_ONLIN, 0) == 0)
Y  			{
Y! 			printf("tms%d ONLIN", ctlr);
Y  			return(-1);
Y  			}
Y! 		tms_offline[ctlr][tms->tmscp_cmd.mscp_unit] = 0;
Y  		}
Y  	tmscpclose(io);		/* close just does a rewind */
Y! 	if (io->i_boff < 0) {
Y! 		printf("tms%d bad offset", ctlr);
Y! 		return(-1);
Y! 	}
Y! 	else if (io->i_boff > 0)
Y  		/*
Y  		 * Skip forward the appropriate number of files on the tape.
Y  		 */
Y  		{
Y! 		tms->tmscp_cmd.mscp_tmkcnt = io->i_boff;
Y  		tms->tmscp_cmd.mscp_buffer_h = 0;
Y  		tms->tmscp_cmd.mscp_bytecnt = 0;
Y  		tmscpcmd(ctlr, M_OP_REPOS, 0);
Y--- 144,169 ----
Y  			}
Y  		tmsoffline[ctlr] = 0;
Y  		}
Y! 	tms->tmscp_cmd.mscp_unit = unit;
Y  	/* 
Y  	 * Has this unit been issued an ONLIN?
Y  	 */
Y! 	if (tms_offline[ctlr][unit])
Y  		{
Y  		if (tmscpcmd(ctlr, M_OP_ONLIN, 0) == 0)
Y  			{
Y! 			printf("tms%d,%d ONLIN", ctlr, unit);
Y  			return(-1);
Y  			}
Y! 		tms_offline[ctlr][unit] = 0;
Y  		}
Y  	tmscpclose(io);		/* close just does a rewind */
Y! 	if	(io->i_part > 0)
Y  		/*
Y  		 * Skip forward the appropriate number of files on the tape.
Y  		 */
Y  		{
Y! 		tms->tmscp_cmd.mscp_tmkcnt = io->i_part;
Y  		tms->tmscp_cmd.mscp_buffer_h = 0;
Y  		tms->tmscp_cmd.mscp_bytecnt = 0;
Y  		tmscpcmd(ctlr, M_OP_REPOS, 0);
Y***************
Y*** 179,192 ****
Y  tmscpclose(io)
Y  	register struct iob *io;
Y  {
Y! 	register int ctlr = CTLRn(io->i_unit);
Y! 	register struct tmscp *tms = &tmscp[ctlr];
Y  
Y  	tms->tmscp_cmd.mscp_buffer_l = 0;	/* tmkcnt */
Y  	tms->tmscp_cmd.mscp_buffer_h = 0;
Y  	tms->tmscp_cmd.mscp_bytecnt = 0;
Y! 	tms->tmscp_cmd.mscp_unit = UNITn(io->i_unit);
Y! 	tmscpcmd(ctlr, M_OP_REPOS, M_MD_REWND | M_MD_CLSEX);
Y  }
Y   
Y  /*
Y--- 178,190 ----
Y  tmscpclose(io)
Y  	register struct iob *io;
Y  {
Y! 	register struct tmscp *tms = &tmscp[io->i_ctlr];
Y  
Y  	tms->tmscp_cmd.mscp_buffer_l = 0;	/* tmkcnt */
Y  	tms->tmscp_cmd.mscp_buffer_h = 0;
Y  	tms->tmscp_cmd.mscp_bytecnt = 0;
Y! 	tms->tmscp_cmd.mscp_unit = io->i_unit;
Y! 	tmscpcmd(io->i_ctlr, M_OP_REPOS, M_MD_REWND | M_MD_CLSEX);
Y  }
Y   
Y  /*
Y***************
Y*** 200,215 ****
Y  	register struct tmscp *tms = &tmscp[ctlr];
Y  	register struct mscp *mp;	/* ptr to cmd packet */
Y  	int i;				/* read into to init polling */
Y   
Y  	/*
Y  	 * Init cmd & rsp area
Y  	 */
Y! 	tms->tmscp_ca.ca_cmddsc[0].lsh = (short)&tms->tmscp_cmd.mscp_cmdref;
Y! 	tms->tmscp_ca.ca_cmddsc[0].hsh = segflag;
Y  	tms->tmscp_cmd.mscp_dscptr = (long *)tms->tmscp_ca.ca_cmddsc;
Y  	tms->tmscp_cmd.mscp_header.tmscp_vcid = 1;	/* for tape */
Y! 	tms->tmscp_ca.ca_rspdsc[0].lsh = (short)&tms->tmscp_rsp.mscp_cmdref;
Y! 	tms->tmscp_ca.ca_rspdsc[0].hsh = segflag;
Y  	tms->tmscp_rsp.mscp_dscptr = (long *)tms->tmscp_ca.ca_rspdsc;
Y  	tms->tmscp_cmd.mscp_cntflgs = 0;
Y  
Y--- 198,217 ----
Y  	register struct tmscp *tms = &tmscp[ctlr];
Y  	register struct mscp *mp;	/* ptr to cmd packet */
Y  	int i;				/* read into to init polling */
Y+ 	int	bae, lo16;
Y   
Y  	/*
Y  	 * Init cmd & rsp area
Y  	 */
Y! 	iomapadr(&tms->tmscp_cmd.mscp_cmdref, &bae, &lo16);
Y! 	tms->tmscp_ca.ca_cmddsc[0].lsh = lo16;
Y! 	tms->tmscp_ca.ca_cmddsc[0].hsh = bae;
Y  	tms->tmscp_cmd.mscp_dscptr = (long *)tms->tmscp_ca.ca_cmddsc;
Y  	tms->tmscp_cmd.mscp_header.tmscp_vcid = 1;	/* for tape */
Y! 
Y! 	iomapadr(&tms->tmscp_rsp.mscp_cmdref, &bae, &lo16);
Y! 	tms->tmscp_ca.ca_rspdsc[0].lsh = lo16;
Y! 	tms->tmscp_ca.ca_rspdsc[0].hsh = bae;
Y  	tms->tmscp_rsp.mscp_dscptr = (long *)tms->tmscp_ca.ca_rspdsc;
Y  	tms->tmscp_cmd.mscp_cntflgs = 0;
Y  
Y***************
Y*** 225,231 ****
Y  	for (;;)
Y  		{
Y  		if (TMScsr[ctlr]->tmscpsa & TMSCP_ERR) {
Y! 			printf("tmscp%d: Fatal error sa=%o\n",
Y  				ctlr, TMScsr[ctlr]->tmscpsa);
Y  			return(0);
Y  		}
Y--- 227,233 ----
Y  	for (;;)
Y  		{
Y  		if (TMScsr[ctlr]->tmscpsa & TMSCP_ERR) {
Y! 			printf("tms%d: Fatal error sa=%o\n",
Y  				ctlr, TMScsr[ctlr]->tmscpsa);
Y  			return(0);
Y  		}
Y***************
Y*** 258,263 ****
Y--- 260,267 ----
Y  			tapemark = 1;
Y  			return(1);
Y  		}
Y+ 		printf("tms%d,%d: I/O err 0%o op=0%o mod=0%o\n", ctlr,
Y+ 			mp->mscp_unit, mp->mscp_status, op, mod);
Y  		return(0);
Y  	}
Y  	return(1);
Y***************
Y*** 270,276 ****
Y  	register struct iob *io;
Y  	int func;
Y  {
Y! 	int ctlr = CTLRn(io->i_unit);
Y  	register struct tmscp *tms = &tmscp[ctlr];
Y  	register struct mscp *mp;
Y   
Y--- 274,281 ----
Y  	register struct iob *io;
Y  	int func;
Y  {
Y! 	int	ctlr = io->i_ctlr, unit = io->i_unit;
Y! 	int	bae, lo16;
Y  	register struct tmscp *tms = &tmscp[ctlr];
Y  	register struct mscp *mp;
Y   
Y***************
Y*** 277,290 ****
Y  	mp = &tms->tmscp_cmd;
Y  	mp->mscp_lbn_l = loint(io->i_bn);
Y  	mp->mscp_lbn_h = hiint(io->i_bn);
Y! 	mp->mscp_unit = UNITn(io->i_unit);
Y  	mp->mscp_bytecnt = io->i_cc;
Y! 	mp->mscp_buffer_l = (u_short)io->i_ma;
Y! 	mp->mscp_buffer_h = segflag;
Y! 	if (tmscpcmd(ctlr, func == READ ? M_OP_READ : M_OP_WRITE, 0)==0) {
Y! 		printf("tms%d,%d: I/O err\n", ctlr, UNITn(io->i_unit));
Y  		return(-1);
Y- 	}
Y  	/*
Y  	 * Detect hitting tape mark so we do it gracefully and return a
Y  	 * character count of 0 to signify end of copy.
Y--- 282,294 ----
Y  	mp = &tms->tmscp_cmd;
Y  	mp->mscp_lbn_l = loint(io->i_bn);
Y  	mp->mscp_lbn_h = hiint(io->i_bn);
Y! 	mp->mscp_unit = unit;
Y  	mp->mscp_bytecnt = io->i_cc;
Y! 	iomapadr(io->i_ma, &bae, &lo16);
Y! 	mp->mscp_buffer_l = lo16;
Y! 	mp->mscp_buffer_h = bae;
Y! 	if	(tmscpcmd(ctlr, func == READ ? M_OP_READ : M_OP_WRITE, 0) ==0)
Y  		return(-1);
Y  	/*
Y  	 * Detect hitting tape mark so we do it gracefully and return a
Y  	 * character count of 0 to signify end of copy.
Y***************
Y*** 293,295 ****
Y--- 297,323 ----
Y  		return(0);
Y  	return(io->i_cc);
Y  }
Y+ 
Y+ tmscpseek(io, space)
Y+ 	register struct iob *io;
Y+ 	int	space;
Y+ 	{
Y+ 	register struct tmscp *tms = &tmscp[io->i_ctlr];
Y+ 	int	mod;
Y+ 
Y+ 	if	(space == 0)
Y+ 		return(0);
Y+ 	if	(space < 0)
Y+ 		{
Y+ 		mod = M_MD_REVRS;
Y+ 		space = -space;
Y+ 		}
Y+ 	else
Y+ 		mod = 0;
Y+ 	tms->tmscp_cmd.mscp_buffer_l = 0;
Y+ 	tms->tmscp_cmd.mscp_buffer_h = 0;
Y+ 	tms->tmscp_cmd.mscp_unit = io->i_unit;
Y+ 	tms->tmscp_cmd.mscp_reccnt = space;
Y+ 	tmscpcmd(io->i_ctlr, M_OP_REPOS, mod | M_MD_OBJCT);
Y+ 	return(0);
Y+ 	}
Y*** /usr/src/sys/pdpstand/ts.c.old	Fri Jul 15 23:52:29 1994
Y--- /usr/src/sys/pdpstand/ts.c	Thu Jun  8 19:38:04 1995
Y***************
Y*** 3,17 ****
Y   * All rights reserved.  The Berkeley software License Agreement
Y   * specifies the terms and conditions for redistribution.
Y   *
Y!  *	@(#)ts.c	2.1 (2.11BSD) 7/15/94
Y   */
Y  
Y  /*
Y!  *	Stand-alone TS11/TU80/TS05/TK25 1600 BPI magtape driver.
Y   */
Y  
Y  #include "../h/param.h"
Y- #include "../h/inode.h"
Y  #include "../pdpuba/tsreg.h"
Y  #include "saio.h"
Y  
Y--- 3,16 ----
Y   * All rights reserved.  The Berkeley software License Agreement
Y   * specifies the terms and conditions for redistribution.
Y   *
Y!  *	@(#)ts.c	2.2 (2.11BSD) 1995/06/08
Y   */
Y  
Y  /*
Y!  *	Stand-alone TS11/TU80/TS05/TK25 magtape driver.
Y   */
Y  
Y  #include "../h/param.h"
Y  #include "../pdpuba/tsreg.h"
Y  #include "saio.h"
Y  
Y***************
Y*** 39,78 ****
Y  tsopen(io)
Y  	register struct iob *io;
Y  {
Y! 	int skip;
Y  	register struct tsdevice *tsaddr;
Y  	register struct ts_char *chrb;
Y  	struct ts_cmd *cmb;
Y! 	int ctlr = CTLRn(io->i_unit);
Y  	char *cp;
Y  
Y  	if (genopen(NTS, io) < 0)
Y  		return(-1);
Y  	tsaddr = TScsr[ctlr];
Y  
Y! 	/* combuf must be alligned on a mod 4 byte boundary */
Y  	cp = (char *)((u_short)softspace + 3 & ~3);
Y  	cp += (ctlr * sizeof (struct ts_cmd));
Y  	cmb = combuf[ctlr] = (struct ts_cmd *)cp;
Y! 	tsptr[ctlr] = (caddr_t)((int)&combuf[ctlr]->c_cmd | (int)segflag);
Y  	cmb->c_cmd = (TS_ACK|TS_CVC|TS_INIT);
Y  	tsaddr->tsdb = (u_short) tsptr[ctlr];
Y  	while ((tsaddr->tssr & TS_SSR) == 0)
Y  		continue;
Y  	chrb = &chrbuf[ctlr];
Y! 	chrb->char_bptr = (u_short) &mesbuf;
Y! 	chrb->char_bae = segflag;
Y  	chrb->char_size = 016;
Y  	chrb->char_mode = 0;
Y  	cmb->c_cmd = (TS_ACK|TS_CVC|TS_SETCHR);
Y! 	cmb->c_loba = (u_short) &chrbuf;
Y! 	cmb->c_hiba = segflag;
Y  	cmb->c_size = 010;
Y  	tsaddr->tsdb = (u_short) tsptr[ctlr];
Y  	while ((tsaddr->tssr & TS_SSR) == 0)
Y  		continue;
Y  	tsstrategy(io, TS_REW);
Y! 	skip = io->i_boff;
Y  	while (skip--) {
Y  		io->i_cc = 0;
Y  		while (tsstrategy(io, TS_SFORWF))
Y--- 38,85 ----
Y  tsopen(io)
Y  	register struct iob *io;
Y  {
Y! 	int	skip, bae, lo16;
Y  	register struct tsdevice *tsaddr;
Y  	register struct ts_char *chrb;
Y  	struct ts_cmd *cmb;
Y! 	int ctlr = io->i_ctlr;
Y  	char *cp;
Y  
Y  	if (genopen(NTS, io) < 0)
Y  		return(-1);
Y+ 	io->i_flgs |= F_TAPE;
Y  	tsaddr = TScsr[ctlr];
Y  
Y! 	/* combuf must be aligned on a mod 4 byte boundary */
Y  	cp = (char *)((u_short)softspace + 3 & ~3);
Y  	cp += (ctlr * sizeof (struct ts_cmd));
Y  	cmb = combuf[ctlr] = (struct ts_cmd *)cp;
Y! 
Y! 	iomapadr(cmb, &bae, &lo16);
Y! 	tsptr[ctlr] = (caddr_t)(lo16 | bae);
Y  	cmb->c_cmd = (TS_ACK|TS_CVC|TS_INIT);
Y  	tsaddr->tsdb = (u_short) tsptr[ctlr];
Y  	while ((tsaddr->tssr & TS_SSR) == 0)
Y  		continue;
Y+ 
Y  	chrb = &chrbuf[ctlr];
Y! 	iomapadr(&mesbuf, &bae, &lo16);
Y! 	chrb->char_bptr = lo16;
Y! 	chrb->char_bae = bae;
Y  	chrb->char_size = 016;
Y  	chrb->char_mode = 0;
Y+ 
Y  	cmb->c_cmd = (TS_ACK|TS_CVC|TS_SETCHR);
Y! 	iomapadr(&chrbuf, &bae, &lo16);
Y! 	cmb->c_loba = lo16;
Y! 	cmb->c_hiba = bae;
Y  	cmb->c_size = 010;
Y  	tsaddr->tsdb = (u_short) tsptr[ctlr];
Y  	while ((tsaddr->tssr & TS_SSR) == 0)
Y  		continue;
Y+ 
Y  	tsstrategy(io, TS_REW);
Y! 	skip = io->i_part;
Y  	while (skip--) {
Y  		io->i_cc = 0;
Y  		while (tsstrategy(io, TS_SFORWF))
Y***************
Y*** 90,105 ****
Y  tsstrategy(io, func)
Y  	register struct iob *io;
Y  {
Y! 	register int ctlr = CTLRn(io->i_unit);
Y! 	int errcnt, unit;
Y  	register struct tsdevice *tsaddr = TScsr[ctlr];
Y  
Y- 	unit = UNITn(io->i_unit);
Y  	errcnt = 0;
Y! 	combuf[ctlr]->c_loba = (u_short) io->i_ma;
Y! 	combuf[ctlr]->c_hiba = segflag;
Y  	combuf[ctlr]->c_size = io->i_cc;
Y! 	if (func == TS_SFORW || func == TS_SFORWF)
Y  		combuf[ctlr]->c_repcnt = 1;
Y  	if (func == READ)
Y  		combuf[ctlr]->c_cmd = TS_ACK|TS_RCOM;
Y--- 97,113 ----
Y  tsstrategy(io, func)
Y  	register struct iob *io;
Y  {
Y! 	register int ctlr = io->i_ctlr;
Y! 	int	errcnt, unit = io->i_unit, bae, lo16;
Y  	register struct tsdevice *tsaddr = TScsr[ctlr];
Y  
Y  	errcnt = 0;
Y! 	iomapadr(io->i_ma, &bae, &lo16);
Y! 	combuf[ctlr]->c_loba = lo16;
Y! 	combuf[ctlr]->c_hiba = bae;
Y  	combuf[ctlr]->c_size = io->i_cc;
Y! 	if (func == TS_SFORW || func == TS_SFORWF || func == TS_SREV || 
Y! 	    func == TS_SREVF)
Y  		combuf[ctlr]->c_repcnt = 1;
Y  	if (func == READ)
Y  		combuf[ctlr]->c_cmd = TS_ACK|TS_RCOM;
Y***************
Y*** 117,124 ****
Y  	}
Y  	if (tsaddr->tssr & TS_SC) {
Y  		if (errcnt == 0)
Y! 		    printf("\nTS%d,%d err sr=%o xs0=%o xs1=%o xs2=%o xs3=%o",
Y! 			ctlr, UNITn(io->i_unit), tsaddr->tssr,
Y  			mesbuf[ctlr].s_xs0, mesbuf[ctlr].s_xs1,
Y  			mesbuf[ctlr].s_xs2, mesbuf[ctlr].s_xs3);
Y  		if (errcnt++ == 10) {
Y--- 125,132 ----
Y  	}
Y  	if (tsaddr->tssr & TS_SC) {
Y  		if (errcnt == 0)
Y! 		    printf("\nts%d,%d err sr=%o xs0=%o xs1=%o xs2=%o xs3=%o",
Y! 			ctlr, unit, tsaddr->tssr,
Y  			mesbuf[ctlr].s_xs0, mesbuf[ctlr].s_xs1,
Y  			mesbuf[ctlr].s_xs2, mesbuf[ctlr].s_xs3);
Y  		if (errcnt++ == 10) {
Y***************
Y*** 130,136 ****
Y  		else if (func == WRITE)
Y  			combuf[ctlr]->c_cmd = (TS_ACK|TS_RETRY|TS_WCOM);
Y  		else {
Y! 			printf("\n");
Y  			return(-1);
Y  		}
Y  		tsaddr->tsdb = (u_short) tsptr[ctlr];
Y--- 138,144 ----
Y  		else if (func == WRITE)
Y  			combuf[ctlr]->c_cmd = (TS_ACK|TS_RETRY|TS_WCOM);
Y  		else {
Y! 			putchar('\n');
Y  			return(-1);
Y  		}
Y  		tsaddr->tsdb = (u_short) tsptr[ctlr];
Y***************
Y*** 138,140 ****
Y--- 146,169 ----
Y  	}
Y  	return (io->i_cc+mesbuf[ctlr].s_rbpcr);
Y  }
Y+ 
Y+ tsseek(io, space)
Y+ 	register struct iob *io;
Y+ 	int	space;
Y+ 	{
Y+ 	int	fnc;
Y+ 
Y+ 	if	(space < 0)
Y+ 		{
Y+ 		fnc = TS_SREV;
Y+ 		space = -space;
Y+ 		}
Y+ 	else
Y+ 		fnc = TS_SFORW;
Y+ 	while	(space--)
Y+ 		{
Y+ 		io->i_cc = 0;
Y+ 		tsstrategy(io, fnc);
Y+ 		}
Y+ 	return(0);
Y+ 	}
Y*** /usr/src/sys/pdpstand/xp.c.old	Sat May  4 17:49:43 1991
Y--- /usr/src/sys/pdpstand/xp.c	Thu Jun  8 19:38:21 1995
Y***************
Y*** 3,9 ****
Y   * All rights reserved.  The Berkeley software License Agreement
Y   * specifies the terms and conditions for redistribution.
Y   *
Y!  *	@(#)xp.c	2.0 (2.11BSD) 4/20/91
Y   */
Y  
Y  /*
Y--- 3,9 ----
Y   * All rights reserved.  The Berkeley software License Agreement
Y   * specifies the terms and conditions for redistribution.
Y   *
Y!  *	@(#)xp.c	2.1 (2.11BSD) 1995/06/08
Y   */
Y  
Y  /*
Y***************
Y*** 10,16 ****
Y   * SMD disk driver
Y   */
Y  #include "../h/param.h"
Y- #include "../h/inode.h"
Y  #include "../pdpuba/hpreg.h"
Y  #include "../machine/iopage.h"
Y  #include "saio.h"
Y--- 10,15 ----
Y***************
Y*** 32,43 ****
Y  xpstrategy(io, func)
Y  	register struct iob *io;
Y  {
Y! 	int unit = UNITn(io->i_unit);
Y! 	int ctlr = CTLRn(io->i_unit);
Y  	int i;
Y  	register nm_sect_per_cyl, nsect;
Y  	daddr_t bn;
Y! 	int sn, cn, tn;
Y  	struct hpdevice *xpaddr = XPcsr[ctlr];
Y  
Y  	bn = io->i_bn;
Y--- 31,42 ----
Y  xpstrategy(io, func)
Y  	register struct iob *io;
Y  {
Y! 	int unit = io->i_unit;
Y! 	int ctlr = io->i_ctlr;
Y  	int i;
Y  	register nm_sect_per_cyl, nsect;
Y  	daddr_t bn;
Y! 	int sn, cn, tn, bae, lo16;
Y  	struct hpdevice *xpaddr = XPcsr[ctlr];
Y  
Y  	bn = io->i_bn;
Y***************
Y*** 113,123 ****
Y  	tn = sn/nsect;
Y  	sn = sn%nsect;
Y  
Y  	xpaddr->hpdc = cn;
Y  	xpaddr->hpda = (tn << 8) + sn;
Y! 	xpaddr->hpba = io->i_ma;
Y  	xpaddr->hpwc = -(io->i_cc>>1);
Y! 	i = (segflag << 8) | HP_GO;
Y  	if (func == READ)
Y  		i |= HP_RCOM;
Y  	else if (func == WRITE)
Y--- 112,123 ----
Y  	tn = sn/nsect;
Y  	sn = sn%nsect;
Y  
Y+ 	iomapadr(io->i_ma, &bae, &lo16);
Y  	xpaddr->hpdc = cn;
Y  	xpaddr->hpda = (tn << 8) + sn;
Y! 	xpaddr->hpba = (caddr_t)lo16;
Y  	xpaddr->hpwc = -(io->i_cc>>1);
Y! 	i = (bae << 8) | HP_GO;
Y  	if (func == READ)
Y  		i |= HP_RCOM;
Y  	else if (func == WRITE)
SHAR_EOF
fi
exit 0
#	End of shell archive
