ramd1of1 Version 3.1 - Ram disk driver

Berny Goodheart berny at tndsyd.oz.au
Mon May 20 22:10:42 AEST 1991


This posting consists of a new version of the RAM disk driver
posted earlier this year. The main changes are for the support
of System V.4.0 ESIX (thanks to Ron Bolin) and also better 
installation facilities. There are also some bug fixes.

This is a ram disk for UNIX System V.2, V.3 and System V.4 systems
It has been specifically written for the 286/386 PC versions of UNIX
in particular it has been tested on the following versions (mainly
because I can't get to other versions):

Microport:		System V/AT 286 All Versions
			System V/386	All Versions
Bell Technology:	UNIX System V Release 3.0
Interactive Systems:	386/ix 3.2
SCO:			System V.3
ESIX SYSTEMS:		UNIX System V Release 4.0 Rev  A

However, the driver is pretty generic and should not take much
modification to work on other TRUE AT&T type UNIXes.

It has been used extensively by a number of users since 1987 with
few if any problems, but I will keep watch in comp.sources.bugs
for any feedback.

If anyone changes or modifies this code please send me the details so
that I can pass it on to everyone else. Also I should like to here
about other systems it has been ported to other than those mentioned above.

If you mail your email address I will endevour to keep you informed
of any updates from time to time. (See the file called REGISTER)

Berny Goodheart (berny at tndsyd.oz@munnari.oz.au)

-------------------- CUT HERE -----------------------------------------
# This is a shell archive.  Remove anything before this line
# then unpack it by saving it in a file and typing "sh file"
# (Files unpacked will be owned by you and have default permissions).
# This archive contains the following files:
#	./contrib/pflopp
#	./contrib/upflopp
#	./contrib/upflopp.1m
#	./INFO.V2
#	./INFO.V3
#	./INFO.V4
#	./MANIFEST
#	./Makefile.V2
#	./Makefile.V3
#	./Makefile.V4
#	./README
#	./REGISTER
#	./S06TMPRAMD
#	./install.V2
#	./magic.V2
#	./ramd.7
#	./ramd.c
#	./ramd.h
#	./ramd_dfile
#	./ramd_master
#	./ramd_mdev
#	./ramd_node
#	./ramd_sdev
#	./raminit
#	./raminit.1m
#	./ramrc.d
#	./ramstat.1m
#	./ramstat.c
#	./ramtab
#
if `test ! -d ./contrib`
then
  mkdir ./contrib
  echo "mkdir ./contrib"
fi
if `test ! -s ./contrib/pflopp`
then
echo "writing ./contrib/pflopp"
cat > ./contrib/pflopp << '\gux-shar\'
#!/bin/sh

# Use the Ram-disk as a pseudo-floppy

# Check if the file is compressed

ic=0
if [ -f ${1}.Z ]
then
  ic=1
fi

# Get the size of the file

chars=`wc -c $1 | cut -f1 -d" "`
blocks=`expr ${chars} / 4096`

# Find a free floppy-device

ramnr=`ramstat | egrep closed | awk 'NR == 1 { print $1 }'`

if [ -z "$ramnr" ]
then
  echo "No free RAM-devices"
  exit 1
fi

CRAM=/dev/rdsk/ram${ramnr}
BRAM=/dev/dsk/ram${ramnr}
MP=/floppy${ramnr}

# Create the RAM-area

ramstat -i ${blocks} $CRAM

# Copy the image of the floppy to the RAM-disk

if [ $ic -eq 1 ]
then	
  uncompress < $1 | dd of=$CRAM bs=4k
else
  dd if=$1 of=$CRAM bs=4k
fi

# Check that the mountpoint exists

if [ ! -d $MP ]
then
  mkdir $MP
fi

# Mount the pseudo-floppy

mount $BRAM $MP
echo $MP



\gux-shar\
else
  echo "will not over write ./contrib/pflopp"
fi
if `test ! -s ./contrib/upflopp`
then
echo "writing ./contrib/upflopp"
cat > ./contrib/upflopp << '\gux-shar\'
#!/bin/sh

# upflopp
#		- Umount pseudo-floppy and store image in file.

#	upflopp ramnr file

ramnr=$1

umount /floppy${ramnr}

dd if=/dev/rdsk/ram${ramnr} of=$2 bs=4k

ramstat -r /dev/dsk/ram${ramnr} /dev/rdsk/ram${ramnr}


\gux-shar\
else
  echo "will not over write ./contrib/upflopp"
fi
if `test ! -s ./contrib/upflopp.1m`
then
echo "writing ./contrib/upflopp.1m"
cat > ./contrib/upflopp.1m << '\gux-shar\'
.TH PFLOPP 1M
.SH NAME
.B pflopp,upflopp
\- Mount/unmount pseudo floppy from disk-image.
.SH SYNOPSIS
.B pflopp file
.br
.B upflopp number file
.SH DESCRIPTION
.B Pflopp
is a shell-script that uses the ram-disk as a pseudo floppy. It is used when
an image of a floppy has been created with dd and it is necessary to make
changes to the file-system without copying it to the real floppy.

.B Pflopp
takes one argument, which is the file that contains the image of
the floppy. It automagically searches for a free ram-disk device and
echos the mount-point to standard output.

.B Upflopp
is a shell-script that unmounts a pseudo-floppy. It takes two arguments:
the first argumtent corresponds to the minor-number of the ram-disk
device. The second number is the file that the new image should be stored
in.

.SH FILES
/dev/rdsk/ram?
.br
/dev/dsk/ram?
.br
/floppy?

.SH SEE ALSO
dd(1),ramstat(1M)
	
.SH AUTHOR
Jan Akalla

\gux-shar\
else
  echo "will not over write ./contrib/upflopp.1m"
fi
if `test ! -s ./INFO.V2`
then
echo "writing ./INFO.V2"
cat > ./INFO.V2 << '\gux-shar\'

  	@(#)INFO.V2	1.1 Copyright (C) B.M.Goodheart 1987, 1988, 1989, 1990 

	  Installation instructions for Microport System V/AT.

	The following instructions will help you install the Ram
	disk device driver onto your system. You will need the
	Microport System V/AT Development Package and the Link
	Kit package installed on your system.

	The process of adding the driver to your system
	is a fairly straight forward process, providing
	you take care and read these instructions carefully
	before you proceed.

			    INSTRUCTIONS
		    	    ============

	1. 	You will need to be Logged in as 'root'

	2.  	Make a backup of your current kernel.
		Enter the following command:
			cp /system5 /system5.orig

	3.	Edit the file "Makefile.V2" and change the variable
		LINKDIR (default is /etc/linkkit) which specifies the
		full path name of your link kit directory.

	4.	The file 'ramtab' may need to be changed
		to reflect your ramdisk initialization requirements.
		Edit this file to suite your requirements, the default
		configuration is. 
			
			1 ramdisk only mounted on '/tmp'
			labeled 'tmp'
			containing '500' blocks
			including '150' inodes

	5.	Edit the file "ramd_master" file. This file contains
		a single record with fields 6 & 7 set to their 
		default Major numbers of 13 and 14. You will probably
		need to modify these to suite your installation. 
		Field 6 is the BLOCK device Major number for block
		special files /dev/dsk/ram?, Field 7 is the CHARACTER
		device Major number for the character special files
		/dev/ctrlram and /dev/rdsk/ram?
		You must also edit the file "install.V2" and modify
		the variables BLOCKNO and CHARNO. These variables should
		be set to the same values as specified in "ramd_master".

	6.	Run the makefile by typing:
			make -f Makefile.V2 install

	7.	Change directory into your linkkit/cf directory and
		enter the following command:
			make wini

	8.	When the kernel make has finished the new kernel
		will be in the linkkit directory. You can now copy
		the new kernel into the root directory as follows:

		cp ../system5 /system5
		sync;sync



	9. 	The Ram disk has now been installed.
		Now reboot the system by pressing Ctrl-Alt-Del.

\gux-shar\
else
  echo "will not over write ./INFO.V2"
fi
if `test ! -s ./INFO.V3`
then
echo "writing ./INFO.V3"
cat > ./INFO.V3 << '\gux-shar\'

  	@(#)INFO.V3	1.1 Copyright (C) B.M.Goodheart 1987, 1988, 1989, 1991 

	  Installation instructions for V.3 versions

	The following instructions will help you install the Ram
	disk device driver onto your V.3 UNIX system. You will need the
	Development Package and the Kernel Build Kit installed on your system.

	The process of adding this driver to your system
	is a fairly straight forward process, providing
	you take care and read these instructions carefully
	before you proceed.


			    INSTRUCTIONS
		    	    ============

	1. 	You need to be logged in as 'root'


	2.	Edit the file "ramd_mdev" file. This file contains
		a single record with fields 5 & 6 set to their 
		default Major numbers of 2 and 26. You will probably
		need to modify these to suite your installation. 
		Field 5 is the BLOCK device Major number for block
		special files /dev/dsk/ram?, Field 6 is the CHARACTER
		device Major number for the character special files
		/dev/ctrlram and /dev/rdsk/ram?

	3.	The file 'ramtab' may need to be changed
		to reflect your ramdisk initialization requirements.
		Edit this file to suite your requirements, the default
		configuration is. 
			
			1 ramdisk only mounted on '/tmp'
			labeled 'tmp'
			containing '500' 4k blocks (2 Meg ram disk)
			with '150' inodes

	4.	If you currently use the standard supplied RAM Disk
		Driver you should keep a copy of the /etc/rc2.d/S06TMPRAMD
		file. This file is overwritten by the Makefile.

	5.	Make sure you copy your old kernel: 
			cp /unix /unix.orig
	
	6.	You are now ready to make the driver and install it.
		type:
			 make -f Makefile.V3 install

	7.	You will then have to rebuild the kernel and reboot. 


\gux-shar\
else
  echo "will not over write ./INFO.V3"
fi
if `test ! -s ./INFO.V4`
then
echo "writing ./INFO.V4"
cat > ./INFO.V4 << '\gux-shar\'

  	@(#)INFO.V4	1.1 Copyright (C) B.M.Goodheart 1987, 1988, 1989, 1991 

	  Installation instructions for V.4 versions

	The following instructions will help you install the Ram
	disk device driver onto your V.4 UNIX system. You will need the
	Development Package and the Kernel Build Kit installed on your system.

	The process of adding this driver to your system
	is a fairly straight forward process, providing
	you take care and read these instructions carefully
	before you proceed.


			    INSTRUCTIONS
		    	    ============

	1. 	You need to be logged in as 'root'


	2.	Edit the file "ramd_mdev" file. This file contains
		a single record with fields 5 & 6 set to their 
		default Major numbers of 2 and 26. You will probably
		need to modify these to suite your installation. 
		Field 5 is the BLOCK device Major number for block
		special files /dev/dsk/ram?, Field 6 is the CHARACTER
		device Major number for the character special files
		/dev/ctrlram and /dev/rdsk/ram?

	3.	The file 'ramtab' may need to be changed
		to reflect your ramdisk initialization requirements.
		Edit this file to suite your requirements, the default
		configuration is. 
			
			1 ramdisk only mounted on '/tmp'
			labeled 'tmp'
			containing '500' 4k blocks (2 Meg ram disk)
			with '150' inodes

	4.	If you currently use the standard supplied RAM Disk
		Driver you should keep a copy of the /etc/rc2.d/S06TMPRAMD
		file. This file is overwritten by the Makefile.

	5.	Make sure you copy your old kernel: 
			cp /unix /unix.orig
	
	6.	You are now ready to make the driver and install it.
		type:
			 make -f Makefile.V4 install

	7.	You will then have to rebuild the kernel and reboot. 


\gux-shar\
else
  echo "will not over write ./INFO.V4"
fi
if `test ! -s ./MANIFEST`
then
echo "writing ./MANIFEST"
cat > ./MANIFEST << '\gux-shar\'
INFO.V2		- Installation information for Microport System V/AT
INFO.V3		- Installation information for V.3 versions
INFO.V4		- Installation information for V.4 versions
MANIFEST	- This file
Makefile.V2 	- SV2 Makefile (For Microport System V/AT only)
Makefile.V3 	- SV3 Makefile
Makefile.V4 	- SV4 Makefile
README 		- Release information for all versions
S06TMPRAMD	- startup /etc/rc2.d ramdisk allocator
contrib		- Directory containing contributed utilities.
install.V2	- Microport specific script for the Makefile
magic.V2	- Microport specific script for the Makefile
ramd.7		- man page
ramd.c		- driver source
ramd.h		- driver /usr/include/sys header file
ramd_dfile	- Microport specific file for dfile.wini
ramd_master	- Microport specific file for master
ramd_mdev	- configuration master file entry
ramd_node	- configuration node entry
ramd_sdev	- configuration sdevices entry
raminit		- /bin/sh interface for processing RAMDisks
raminit.1m	- man page
ramrc.d		- Microport specific start up script for the rc2.d directory
ramstat.1m	- man page
ramstat.c	- user interface to driver
ramtab 		- RAMDisk setup parameter file
\gux-shar\
else
  echo "will not over write ./MANIFEST"
fi
if `test ! -s ./Makefile.V2`
then
echo "writing ./Makefile.V2"
cat > ./Makefile.V2 << '\gux-shar\'
# @(#)Makefile.V2	1.1
# Makefile for Microport System V/AT

DEFS=
CFLAGS = -Ml -c $(DEFS)
LINKDIR = /usr/usr/linkkit
LDFLAGS =
CC=cc

MAN1DIR = /usr/catman/l_man/man1
MAN7DIR = /usr/catman/l_man/man7

all:	ramd xramstat

ramd:	ramd.c ramd.h
	cp ramd.h /usr/include/sys
	chown bin /usr/include/sys/ramd.h
	chgrp bin /usr/include/sys/ramd.h
	chmod 444 /usr/include/sys/ramd.h
	$(CC) $(CFLAGS) ramd.c


conf: 
	ar rv $(LINKDIR)/lib2 ramd.o


iramtab:	
	@if [ ! -f /etc/ramtab ]; then \
		cp ramtab /etc/ramtab ; \
		chmod 644 /etc/ramtab ; \
	fi


rammdev:
	cp $(LINKDIR)/cf/master $(LINKDIR)/cf/master.old
	grep -v "^ramd" $(LINKDIR)/cf/master > /tmp/m$$
	chmod +x magic.V2
	./magic.V2 /tmp/m$$ > $(LINKDIR)/cf/master
	rm -f /tmp/m$$

ramnode:
	./install.V2
	
ramsdev:
	grep -v "^ramd" $(LINKDIR)/cf/dfile.wini > /tmp/m$$
	cat ramd_dfile >> /tmp/m$$
	mv /tmp/m$$ $(LINKDIR)/cf/dfile.wini
	chmod 444 $(LINKDIR)/cf/dfile.wini

xramstat:	ramstat.c ramd.h
	$(CC) $(DEFS) -O -s ramstat.c -o ramstat

iramstat:	ramstat
	cp ramstat /bin/ramstat
	chmod 555 /bin/ramstat
	chmod u+s /bin/ramstat
	

raminit:
	cp raminit /etc/raminit
	chmod 555 /etc/raminit


man:	raminit.1m ramstat.1m ramd.7
	nroff -man raminit.1m | compress -c > $(MAN1DIR)/raminit.1m.Z
	nroff -man ramstat.1m | compress -c > $(MAN1DIR)/ramstat.1m.Z
	nroff -man ramd.7 | compress -c > $(MAN7DIR)/ramd.7.Z


rc:	
	cp ramrc.d /etc/rc2.d
	chmod 555 /etc/rc2.d/ramrc.d


install: all conf iramtab ramnode rammdev ramsdev iramstat raminit man  rc

clean:
	rm -f ramd.o ramstat


cpio:	
	find . -print | cpio -ocv | compress -c > ramd.cpio.Z


tar:	
	tar cvf ramd.tar .

shar:	
	shar -f ramd .
\gux-shar\
else
  echo "will not over write ./Makefile.V2"
fi
if `test ! -s ./Makefile.V3`
then
echo "writing ./Makefile.V3"
cat > ./Makefile.V3 << '\gux-shar\'
# @(#)Makefile.V3	1.1
# Makefile for SV3 and SV4.0 - PROTOTYPED ON ESIX SV4.0 5-10-91 - Ron Bolin
# NOTE: setup for SV3

DEFS= -DSV3 -Di386 # -DSV4
CFLAGS = -c $(DEFS)
LDFLAGS =
CC=cc

#MAN1DIR = /usr/share/man/cat1
MAN1DIR = /usr/catman/l_man/man1
#MAN7DIR = /usr/share/man/cat7
MAN7DIR = /usr/catman/l_man/man7

all:	ramd xramstat

ramd:	ramd.c ramd.h
	cp ramd.h /usr/include/sys
	chown bin /usr/include/sys/ramd.h
	chgrp bin /usr/include/sys/ramd.h
	chmod 444 /usr/include/sys/ramd.h
	$(CC) $(CFLAGS) ramd.c


conf:
	@if [ ! -d /etc/conf/pack.d/ramd ]; then \
	mkdir /etc/conf/pack.d/ramd; \
	chmod 555 /etc/conf/pack.d/ramd; \
	fi ; \
	cp ramd.o /etc/conf/pack.d/ramd/Driver.o


iramtab:	
	@if [ ! -f /etc/ramtab ]; then \
		cp ramtab /etc/ramtab ; \
		chmod 644 /etc/ramtab ; \
	fi


ramnode:
	cp ramd_node /etc/conf/node.d/ramd
	chmod 444 /etc/conf/node.d/ramd

rammdev:
	grep -v "^ramd" /etc/conf/cf.d/mdevice > /tmp/m$$
	cat ramd_mdev >> /tmp/m$$
	mv /tmp/m$$ /etc/conf/cf.d/mdevice

ramsdev:
	@if [ ! -f /etc/conf/sdevice.d/ramd ]; then \
	cp  ramd_sdev /etc/conf/sdevice.d/ramd; \
	fi

xramstat:	ramstat.c ramd.h
	$(CC) $(DEFS) -O -s ramstat.c -o ramstat

iramstat:	ramstat
	cp ramstat /bin/ramstat
	chmod 555 /bin/ramstat
	chmod u+s /bin/ramstat
	

raminit:
	cp raminit /etc/raminit
	chmod 555 /etc/raminit


man:	raminit.1m ramstat.1m ramd.7
	nroff -man raminit.1m | compress -c > $(MAN1DIR)/raminit.1m.Z
	nroff -man ramstat.1m | compress -c > $(MAN1DIR)/ramstat.1m.Z
	nroff -man ramd.7 | compress -c > $(MAN7DIR)/ramd.7.Z


rc:	
	cp S06TMPRAMD /etc/rc2.d
	chmod 555 /etc/rc2.d/S06TMPRAMD


install: all conf iramtab ramnode rammdev ramsdev iramstat raminit man  rc

clean:
	rm -f ramd.o ramstat


cpio:	
	find . -print | cpio -ocv | compress -c > ramd.cpio.Z


tar:	
	tar cvf ramd.tar .

shar:	
	shar -f ramd .
\gux-shar\
else
  echo "will not over write ./Makefile.V3"
fi
if `test ! -s ./Makefile.V4`
then
echo "writing ./Makefile.V4"
cat > ./Makefile.V4 << '\gux-shar\'
# @(#)Makefile.V4	1.1
# Makefile for SV3 and SV4.0 - PROTOTYPED ON ESIX SV4.0 5-10-91 - Ron Bolin
# NOTE: setup for SV4

DEFS= -DSV4 -Di386 # -DSV3
CFLAGS = -c $(DEFS)
LDFLAGS =
CC=cc

MAN1DIR = /usr/share/man/cat1
#MAN1DIR = /usr/catman/l_man/man1
MAN7DIR = /usr/share/man/cat7
#MAN7DIR = /usr/catman/l_man/man7

all:	ramd xramstat

ramd:	ramd.c ramd.h
	cp ramd.h /usr/include/sys
	chown bin /usr/include/sys/ramd.h
	chgrp bin /usr/include/sys/ramd.h
	chmod 444 /usr/include/sys/ramd.h
	$(CC) $(CFLAGS) ramd.c


conf:
	@if [ ! -d /etc/conf/pack.d/ramd ]; then \
	mkdir /etc/conf/pack.d/ramd; \
	chmod 555 /etc/conf/pack.d/ramd; \
	fi ; \
	cp ramd.o /etc/conf/pack.d/ramd/Driver.o


iramtab:	
	@if [ ! -f /etc/ramtab ]; then \
		cp ramtab /etc/ramtab ; \
		chmod 644 /etc/ramtab ; \
	fi


ramnode:
	cp ramd_node /etc/conf/node.d/ramd
	chmod 444 /etc/conf/node.d/ramd

rammdev:
	grep -v "^ramd" /etc/conf/cf.d/mdevice > /tmp/m$$
	cat ramd_mdev >> /tmp/m$$
	mv /tmp/m$$ /etc/conf/cf.d/mdevice

ramsdev:
	@if [ ! -f /etc/conf/sdevice.d/ramd ]; then \
	cp  ramd_sdev /etc/conf/sdevice.d/ramd; \
	fi

xramstat:	ramstat.c ramd.h
	$(CC) $(DEFS) -O -s ramstat.c -o ramstat

iramstat:	ramstat
	cp ramstat /bin/ramstat
	chmod 555 /bin/ramstat
	chmod u+s /bin/ramstat
	

raminit:
	cp raminit /etc/raminit
	chmod 555 /etc/raminit


man:	raminit.1m ramstat.1m ramd.7
	nroff -man raminit.1m | compress -c > $(MAN1DIR)/raminit.1m.Z
	nroff -man ramstat.1m | compress -c > $(MAN1DIR)/ramstat.1m.Z
	nroff -man ramd.7 | compress -c > $(MAN7DIR)/ramd.7.Z


rc:	
	cp S06TMPRAMD /etc/rc2.d
	chmod 555 /etc/rc2.d/S06TMPRAMD


install: all conf iramtab ramnode rammdev ramsdev iramstat raminit man  rc

clean:
	rm -f ramd.o ramstat


cpio:	
	find . -print | cpio -ocv | compress -c > ramd.cpio.Z


tar:	
	tar cvf ramd.tar .

shar:	
	shar -f ramd .
\gux-shar\
else
  echo "will not over write ./Makefile.V4"
fi
if `test ! -s ./README`
then
echo "writing ./README"
cat > ./README << '\gux-shar\'

This is a ram disk for UNIX System V.2, V.3 and System V.4 systems
It has been specifically written for the 286/386 PC versions of UNIX
in particular it has been tested on the following versions (mainly
because I can't get to other versions):

Microport:		System V/AT 286 All Versions
			System V/386	All Versions
Bell Technology:	UNIX System V Release 3.0
Interactive Systems:	386/ix 3.2
SCO:			System V.3
ESIX SYSTEMS:		UNIX System V Release 4.0 Rev  A

However, the driver is pretty generic and should not take much
modification to work on other TRUE AT&T type UNIXes.

It has been used extensively by a number of users since 1987 with
few if any problems, but I will keep watch in comp.sources.bugs
for any feedback.

If anyone changes or modifies this code please send me the details so
that I can pass it on to everyone else. Also I should like to here
about other systems it has been ported to other than those mentioned above.

If you mail your email address I will endevour to keep you informed
of any updates from time to time. (See the file called REGISTER)


INSTALLING:
	Well I have to say that since there are so many 286/386/486
	versions of UNIX/XENIX etc on the market I cannot give
	installation details for each. So it's RTFM I am afraid. Read
	the section in your documentation on how to install device drivers.
	However, Makefiles and installation information is provided
	for the above named systems. Before you start read the INFO.V?
	file for your version of the OS.


MOD INSTALLING 5-10-91 SV4 PORT BY R L BOLIN 

	For SV4.0 see Makefile - You may need to edit
	/etc/conf/cf.d/mdevice for major number devices for the
	RAMDisk (ramd) as default majors are 2 & 26.  Makefile 
	will also work for SV3.2 ISC, ESIX if defined SV3 & i386.

	NOTE: SV4.0 ramd driver - the raminit file is configured for a file
	system of type s5, if you select someother file system you will
	need to adjust the block calculation routine for mkfs.

	BUG: ramstat -m, does not report maxmem correctly - gives 0.  This
	seems to be a BUG in SV4.0 (sysinfo.h).

INFORMATION:

	The ram disk uses a portion of the available user
	memory and configures it as a disk. To the user
	this is totally transparent. The user may read or 
	write to the ram disk in the normal way, indeed
	all standard programs like 'fsck' and 'fsdb' see 
	the ram disk file system just as if it where a file
	system on the hard disk. 


	Obviously you will need enough memory to configure the
	ram disk, the more memory you have the bigger the ram
	disk can be. The ram disk has been designed to allow
	up to 4 virtual disks to reside in memory at any one time.

	The ram disk has undergone some exstensive tests giving
	some amazing results, here is an example: 

	The following criteria was used for the test:

		A 968K Byte C Program in 14 Files, 4 directories, 5 Makefiles
		A PC-AT clone running System V/AT 80286 Running at 12Mhz
		4Mbtye memory fitted
		40 Mbyte Hard disk Average Access 65ms
		Ram disk mounted as /tmp

	RAMDISK SIZE (Blks)	COMPILE TIME (Min:sec)   EFFICENCY RATE
		0			15:09			00%
		500			13:27			12%
		1000			11:36			25%
		1200			09:56			37%
		1500			09:07			40%
		1800			10:17			33%
		2000			11:50			24%
		2200			14:03			07%
		2500			15:37			-2%

	Conclusion
		Because the ram disk resides in memory and not
		on some physical media such as a hard disk,
		the CPU has direct access to the data without
		suffering any latency time. Using a ram disk in
		this way can be upto 40% more efficient especialy
		during developement, However, as the results above
		show, if too much memory is devoted to the ram 
		disk, the efficiency level starts to drop to 
		almost the same level as having no ram disk installed.
		This is because there is a trade off between the
		operating system needing more memory to work with,
		and the ram disk which assignes portions
		of the memory pool to the user, is hogging it all up.

		(If you take too much memory up in the ram disk, you will
		cause the operating system to use the swap device.)

		It can be seen from these results that the ideal
		size of the ram disk for the V.2 installation
		is 1500 physical blocks assuming 4 Mbyte of memory
		is fitted.
		

*************************************************************************
*************************************************************************
*************************************************************************
	It is VERY IMPORTANT to remember that the ram disk
	resides in memory, this means if the system should
	crash or you should shut the system down without first
	saving the contents of the ram disk, ALL the contents
	of the ram disk WILL have been lost.
*************************************************************************
*************************************************************************
*************************************************************************


\gux-shar\
else
  echo "will not over write ./README"
fi
if `test ! -s ./REGISTER`
then
echo "writing ./REGISTER"
cat > ./REGISTER << '\gux-shar\'

If you like this software and would like me to send you updates
from time to time as they become available please fill out this
registration form and email it to:

	UUCP: uunet!munnari.oz!tndsyd.oz.au!berny
	INTERNET: berny at tndsyd.oz@munnari.oz.au
	DOMAIN: goodheart_berny at tandem.com          
	ACSnet: berny at tndsyd.oz

Send with mail header "Ramdisk register"

----------------------------------------------------------------
NOTE: This is free software but please read the Copyright note and
disclaimer in the source files.
----------------------------------------------------------------

               Email address:
Version of Ramdisk installed:
 Number of Systems installed:
                   OS Vendor:
                  OS Version:
                         CPU:
            Installed Memory:
                    Comments:

\gux-shar\
else
  echo "will not over write ./REGISTER"
fi
if `test ! -s ./S06TMPRAMD`
then
echo "writing ./S06TMPRAMD"
cat > ./S06TMPRAMD << '\gux-shar\'
#	Copyright (c) B.M.Goodheart 1989
#	  All Rights Reserved
#
# This script makes a filesystem on the RAMdisk and mounts it as /tmp if
# that hasn't already been done.


#ident	"@(#)S06TMPRAMD	1.1"
state=$1
case $state in

	'start')
		/etc/raminit -i -v
		;;
	'stop')
		/etc/raminit -r
		;;
esac
\gux-shar\
else
  echo "will not over write ./S06TMPRAMD"
fi
if `test ! -s ./install.V2`
then
echo "writing ./install.V2"
cat > ./install.V2 << '\gux-shar\'

# installation script for the ramdisk for Microport System V/AT
#
# @(#)install.V2	1.1
# 
# Make the nodes foe special files

RAW=/dev/rdsk
BLOCK=/dev/dsk
BLOCKNO=13
CHARNO=14

	for x in 0 1 2 3
	do
		mknod $BLOCK/ram${x} b $BLOCKNO $x
		mknod $RAW/ram${x} c $CHARNO $x
		chmod 644 $BLOCK/ram${x} $RAW/ram${x}
	done

	mknod /dev/ctrlram c $CHARNO 0
	chmod 622 /dev/ctrlram

\gux-shar\
else
  echo "will not over write ./install.V2"
fi
if `test ! -s ./magic.V2`
then
echo "writing ./magic.V2"
cat > ./magic.V2 << '\gux-shar\'



# little magic to update the master file on Microport System V/AT

	(l="`sed -e \"/wini/q\" $1 | wc -l`" ; \
	n="`echo $l | sed -e \"s/	//g\"`" ; \
	sed -e "/wini/q" $1; \
	cat ramd_master; \
	sed "1,${n}d" $1)

\gux-shar\
else
  echo "will not over write ./magic.V2"
fi
if `test ! -s ./ramd.7`
then
echo "writing ./ramd.7"
cat > ./ramd.7 << '\gux-shar\'
.TH RAM 7 
.SH NAME
.B ramd
\- memory resident disk interface
.SH DESCRIPTION
The memory resident disk (ram disk) uses a portion of the available
user memory as a pseudo device configured as far as the user is
concerned, the same as a normal file system. Files are accessed via
the system's normal buffering mechanism and may be read and written
to in the normal way. A raw interface is also provided for direct
serial transmission between the ram disk and the users buffer.
.PP
.PP
.SH RAW INTERFACE
Special filename          semantics.
.br
/dev/ctrlram              control interface
.br
/dev/rdsk/ram0            ram disk 0
.br
/dev/rdsk/ram1            ram disk 1
.br
/dev/rdsk/ram2            ram disk 2
.br
/dev/rdsk/ram3            ram disk 3
.br
.SH BLOCK INTERFACE
/dev/dsk/ram0             ram disk 0
.br
/dev/dsk/ram1             ram disk 1
.br
/dev/dsk/ram2             ram disk 2
.br
/dev/dsk/ram3             ram disk 3
.br
.PP
.SH AUTHOR
B.M.Goodheart 
\gux-shar\
else
  echo "will not over write ./ramd.7"
fi
if `test ! -s ./ramd.c`
then
echo "writing ./ramd.c"
cat > ./ramd.c << '\gux-shar\'

/*
 *
 *  @(#)ramd.c	3.1 Copyright (C) B.M.Goodheart 1987, 1888, 1989, 1991 
 *
 *
 *
 *  		      DISCLAIMER OF WARRANTY. 
 *  This software is distributed "as is" and without warranties as to 
 *  performance of merchantability or any other warranties whether expressed 
 *  or implied. In no event shall the author (the copyright holder) be held 
 *  liable for any loss of profit or any other commercial damage resulting 
 *  from the use or misuse of this software, including but not limited to 
 *  special, incidental, consequential or other damages.  THE USER MUST
 *  ASSUME THE ENTIRE RISK OF USING THIS SOFTWARE.
 *
 *
 *			LISCENSE AGREEMENT
 *	This software is placed	into the public domain and 
 *	may be copied or distributed freely provided no profit or 
 *	gain is made and is used for personal use only and the code 
 *	as distributed retains all copyright notices in the code. 
 *	This includes any copyright statements in the target
 *	binary and executable code produced from the distributed source. 
 *
 *
 *	                DISTRIBUTION NOTE
 * 	This file contains the code for a RAM disk driver for UNIX System 5.2
 *	and System V.3.	It has been designed specifically for Microport's 
 *	System V/AT iAPX286 and Interactive Systems V/386 i386 systems
 * 	but should work with other PC based System V.? ports with only 
 *	minor modifications, specifically the BUFSEL selector on the 80286.
 *	This driver should work on any V.3 implementation on a PC. 
 *	Thanks to Ron Bolin (gatech!sbmsg1!bsts00!rlb), this driver has
 *	now been ported and tested on ESIX System V.4.0.
 *
 *
 *	               IMPORTANT NOTE !!!
 *	Any files or data stored within the ram disks will be 
 *	LOST FOR EVER if the system is brought down for ANY reason.
 *
 *	There are also two other programs distributed associated 
 *	with the driver, they are ramstat(1M) and raminit(1M). 
 *	These are used to control the ram disk driver in user mode 
 *	See also ram(7). There are also some contibuted support
 *	programs in the contrib directory.
 *
 *	Berny Goodheart (berny at tndsyd.oz@munnari.oz.au)
 *
 * Modifications:
 *	20-10-87 (001)	The ramsize array would still hold the ram
 *			size even if could not get memory. This has
 *			now been fixed, variable is now zerod.
 *
 *	23-10-88 (002)	Reduced ambiguouse code, now drops through
 *			to the same statements. (reduces object size)
 *
 *	23-10-88 (003)	malloc() returns 0 not NULL (who cares)
 *
 *	12-11-88 (004)  fixed a really big bug, god knows how it
 *			worked in the first place. basically, almost
 *			all the routines that made reference to
 *			'dev' as passed to the sysentry call
 *			where using the raw data, now uses minor(dev)
 *			to extraxt the device index proper.
 *
 *	19-06-89 (005)  this mod is huge, basically I have added
 *			a switch to the compiler "i386" which will
 *			create the driver for System V.3. The difference
 *			to V.2 is quite large in that the two systems
 *			have different memory managment, V.3 uses Page Tables
 *			to map physical memory to kernel virtual memory.
 *
 *	20-06-89 (006)  fixed the character read overrun which used to
 *			to panic the system.
 *
 *      07-07-89 (007)  fixed the block count overrun check algorithm in
 *                      the strategy routine.
 *
 *	09-08-89 (008)  Added a few macros so that the code is
 *                      easier to read.
 *
 *	30-11-89 (009)  forgot to add the strategy print routine
 *                      Now the system tells you when you run out of
 *                      space in a ram disk.
 *
 *	15-04-91 (010)  Jan Akalla reported this one. Trying to write to
 *			the last block in a Ram disk gave out-of-space error.
 *
 *	10-05-91 (011)	Ported to SVR4 by Ron Bolin (gatech!sbmsg1!bsts00!rlb)
 *			Atlanta, GA.
 *			Also changed function base names from "ram" to
 *			"ramd". Assume this conflicted with other routines
 *			on System VR4 (B.M.G)
 *
 *			
 */

static char *bmgid = 
#ifdef TEST
     "RAM disk Test Version Copyright (C) Berny Goodheart \n";
#elif SV4
     "RAM disk 3.1-(SV4-%s) Copyright (C) Berny Goodheart 5/20/91\n\n";
#else
     "RAM disk 3.1-(%s) Copyright (C) Berny Goodheart 5/20/91\n\n";
#endif

#include <sys/errno.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/signal.h>
#include <sys/dir.h>
#include <sys/user.h>
#include <sys/file.h>
#include <sys/sysmacros.h>
#include <sys/map.h>
#include <sys/buf.h>
#include <sys/ramd.h>			/* header file for this driver  */

#ifdef SV4
#include <sys/uio.h>
#include <sys/kmem.h>
#define cotb		potb
#define iodone		biodone
struct uio		*uio_p;
#endif


#define DSK_PHYS_BLOCK	512		/* bytes in a physical disk block */

#define devnum(bp)	minor((bp)->b_dev) /* gets the minor device number */
#define blknum(bp)	((bp)->b_blkno)	   /* block offset for I/O */
#define RADDR(d)	(ramadd[minor(d)])
#define ROPEN(d)	(ram_opened[minor(d)])
#define RSTAT(d)	(ram_state[minor(d)])
#define RSIZE(d)	(ramsize[minor(d)])

#ifndef i386 				/* (008) */
#include <sys/mmu.h>			/* for BUFSEL selector */
caddr_t mapin();
#define  raddr_t	paddr_t
#define diskblk(x)	(ctob(x))
#define blktophys(bp)	(ctob(ramadd[devnum(bp)]) + diskblk(blknum(bp)));
static char *machtype = "iAPX286";
#else
#include <sys/immu.h>
#include <sys/cmn_err.h>
#define mapin(a,b)	(a)		/* emulate V.2 MMU stuff */
#define raddr_t		caddr_t
#define diskblk(x)	(x * DSK_PHYS_BLOCK)
#define blktophys(bp)	(ramadd[devnum(bp)] + diskblk(blknum(bp)));
static char *machtype = "iAPX386";
#endif

#ifdef SV4
#include <sys/ddi.h>			/* last include rule for DDK */
#endif

static raddr_t ramadd[NRDEVS];		/* base address of ram disk	*/
static int ram_opened[NRDEVS];		/* number of processes sleeping */
static int ram_state[NRDEVS];		/* current ram state		*/
static int ramDebug = 0;		/* debug static flag, 0 = off   */
static char busywait = 0;		/* sleeping processes           */

/*
 * ramsize[n] = holds the size of ram disk in physical memory blocks
 *
 * NOTE on i386 machines
 *      a physical block must be on a 4k boundry i.e 1 block = 4096 bytes
 * 	on iAPX286 machines a physical block is 512 bytes
 * 
 */
static int ramsize[NRDEVS];		




/* 
 * This routine is called whenever a process calls the system
 * call 'open' on this device
 *
 */
ramdopen(dev)
{

	busywait++;
	(ROPEN(dev))++;

	if(ramDebug) 
		(void)printf("Ram-[%d] opened by uid-[%d]\n"
			,minor(dev)
			,u.u_ruid);

	/*
	 *
	 * Mask out any other opens while we are busy.
	 * The kernel does not experience any further CPU
	 * work while this happens, the process is simply
	 * put to sleep and added to the process que until 
	 * awoken later..
	 *
	 */
	while(busywait != 1)	/* mask out ram_opened opens */
		(void)sleep((caddr_t)&busywait, PRIBIO + 1);

	/* 
	 *
	 * Is it a valid device 
	 *
	 */
	if(minor(dev) < 0 || minor(dev) > (NRDEVS - 1)) 
		u.u_error = ENODEV; /* (002) */

	/*
	 * wakeup any pending I/O
	 *
	 */
	busywait--;
	(void)wakeup((caddr_t)&busywait);
}



ramdclose(dev)
{
	ROPEN(dev) = 0; /* only called on last close */
}


/*
 * strategy routine is called by both character and block
 * drivers to do the I/O.
 */
#ifdef SV4
void
#endif
ramdstrategy(bp)
struct buf *bp;
{
	raddr_t physdr;

	/*
	 *
	 * If we slip up with deletion of the ram
	 * disk for some reason and we get here somehow,
	 * then this check will stop any reads 
	 * or writes to possibly now unassigned memory.
	 *
	 */
	if(ram_state[devnum(bp)] == RAM_CLOSED) {
		bp->b_error = EIO;
		bp->b_flags |= B_ERROR;
		bp->b_resid = bp->b_bcount;
		(void)iodone(bp);
		return;
	}


	/* 
	 *
	 * check its a legal block (007)
	 *
	 * changed >= to > "last block gave no space error" (010)
	 */
#if i386
	if((diskblk(blknum(bp))+bp->b_bcount)>(ramsize[devnum(bp)] * PTSIZE)) {
#else
	if(diskblk(blknum(bp)) > diskblk(ramsize[devnum(bp)])) {
#endif
		if(bp->b_flags & B_READ) 
			bp->b_error = EIO;
		else
			bp->b_error = ENOSPC;
		bp->b_flags |= B_ERROR;
		bp->b_resid = bp->b_bcount;
		(void)iodone(bp);
		return;
	}


	/* 
	 * work out which block number in the mapped in RAM array
	 * and convert to a physical address.
	 */
	physdr = blktophys(bp);



	/*
	 * If debug is set then send out to the console
	 *
	 */
	if(ramDebug) 
		(void)printf("Ram%d: blk-[%ld] addr-[0x%lx] bytes-[%d] %s\n"
			,devnum(bp)
			,blknum(bp)
			,physdr
			,bp->b_bcount
			,bp->b_flags & B_READ ? "Read" : "Write");
	

	/*
	 * Do the physical memory transfer I/O
	 */
	if(bp->b_flags & B_READ) 
		(void)bcopy(mapin(physdr,BUFSEL),bp->b_un.b_addr,bp->b_bcount);
	else 
		(void)bcopy(bp->b_un.b_addr,mapin(physdr,BUFSEL),bp->b_bcount);


	/*
	 * because bcopy() does not return anything
	 * we assume all bytes where copied and there is
	 * none left in the buffer to transmit
	 */
	bp->b_resid = 0;


	/*
	 * All finished, free the buffer
	 */
	(void)iodone(bp);

}




/*
 * ramdread
 *
 * Uses ramstrategy for RAW I/O 
 *
 */
ramdread(dev)
int dev;
{
#ifdef SV4
	physiock(ramdstrategy,NULL,dev,B_READ,RSIZE(dev)*PTSIZE,uio_p);
#else
	(void)physio(ramdstrategy,NULL,dev,B_READ);
#endif
}




/*
 * ramdwrite
 *
 * Uses ramstrategy for RAW I/O 
 *
 */
ramdwrite(dev)
int dev;
{
#ifdef SV4
	physio(ramdstrategy,NULL,dev,B_WRITE,RSIZE(dev)*PTSIZE,uio_p);
#else
	(void)physio(ramdstrategy,NULL,dev,B_WRITE);
#endif
}



/*
 * user interface to I/O control
 *
 */
ramdioctl(dev, cmd, arg)
int dev, cmd;
union r_ramst *arg;
{
	register x;
	int intlevel;
#if i386
#ifndef SV4
	caddr_t ptalloc();	/* page table allocation routine */
#endif

	/*
	 * Only super user can set or unset the
	 * ram disks.
	 *
 	 * NOTE: TCMEMINFO is only available on 386
	 */
	if((!suser()) && ((cmd != TCGETRAM) || (cmd != TCMEMINFO)) ) {
#else
	if((!suser()) && cmd != TCGETRAM) {
#endif
		u.u_error = EACCES;
		return;
	}


	switch(cmd) {
		case  TCSETRAM :
			/*
	 		 * This will usually be done by 'ramstat' (hopefully)
			 *
			 * If already open then return with errno
			 */
			if(RSTAT(dev) == RAM_OPEN) {
				u.u_error = EBUSY;
				return;
			}

			/*
			 * arg is the ram size in physical blocks
			 * with which to create the RAM disk.
			 */
			if(arg->r_arg < MINRAMSIZ) {
				u.u_error = EINVAL;
				return;
			}
			RSIZE(dev) = arg->r_arg;



			/*
			 * turn interrupts off
			 */
			intlevel = spl6();


			/* 
			 * Try to get memory
			 * 
			 */
#if i386
#ifdef SV4
			if((RADDR(dev) = kmem_zalloc(RSIZE(dev)*PTSIZE,
					KM_NOSLEEP)) == 0) {
#else /* SV3 */
			if((RADDR(dev) = ptalloc(RSIZE(dev),
					PHYSCONTIG|NOSLEEP)) == 0) {
#endif
#else
			if((RADDR(dev)=malloc(coremap,RSIZE(dev)))== 0){
#endif
				RSIZE(dev) = 0; /* (001) */
				u.u_error = ENOMEM;
				(void)splx(intlevel);
				return;
			}
#ifndef i386 
			/*
			 *
			 * Clear the Memory clicks to zero's
			 *
			 * not needed on i386
			 */
			for (x = 0; x < RSIZE(dev); x++)
				(void)clearseg(RADDR(dev) + x);
#endif


			/*
			 *
			 * Initialization is complete at this point
			 * so set the ram_state flag.
			 *
			 */
			RSTAT(dev) = RAM_OPEN;

			(void)splx(intlevel);

			break;


		case  TCDELRAM :
			/*
			 * No point in deleting if we don't exist
			 *
			 */
			if(RSTAT(dev) == RAM_CLOSED) {
				u.u_error = ENXIO;
				return;
			}

			/*
			 * Cant delete the RAM disk if busy
			 *
			 */
			if(ROPEN(dev) > 1) {
				u.u_error = EBUSY;
				return;
			} else
				ROPEN(dev) = 0;


			/*
			 * Try to free up the memory
			 * else GOD HELP THE WORLD
			 *
			 */
			intlevel = spl6();
#if i386
			/*
 			 * uptfree() and kmem_free() don't return anything
			 */
#ifdef SV4
			(void)kmem_free(RADDR(dev),RSIZE(dev)*PTSIZE);
#else /* SV3 */
			(void)uptfree(RADDR(dev),RSIZE(dev));
#endif
#else
			if(mfree(coremap,RSIZE(dev), RADDR(dev)) == -1) 
				/*
				 * We have to panic here because if we
				 * can't free up the memmory then anything
				 * can happen. (possible hardware fault).
				 *
				 * praise be the lord 
				 */
				(void)panic("ram%d: memory de-allocation error",
					minor(dev));
#endif


			/*
			 * PHEW ! THAT WAS CLOSE
			 *
			 * Reset the parameters to zilch
			 * so that next initialization is setup ok.
			 *
			 */
			RSTAT(dev) = RAM_CLOSED;
			RADDR(dev) = 0;
			RSIZE(dev) = 0;
			(void)splx(intlevel);
			break;

		case  TCGETRAM :
			/*
			 * Get statistics about the RAM disks
			 *
			 */
			for(x = 0; x < NRDEVS;x++) {
				arg->r_rstat.r_dev[x] = x;
				arg->r_rstat.r_blks[x] = ramsize[x];
				arg->r_rstat.r_stat[x] = 
					ram_state[x] == RAM_OPEN ? 1 : 0 ;
				arg->r_rstat.r_opns[x] = ram_opened[x];
				arg->r_rstat.r_addr[x] = (paddr_t)ramadd[x];
				arg->r_rstat.r_dbg = ramDebug == 0 ? 0 : 1 ;
			}
			break;

		case  TCRAMDBG :
			/*
			 *
			 * Toggle ramDebug mode 
			 *
			 */
			ramDebug = ramDebug == 0 ? 1 : 0;
			arg->r_arg = ramDebug;
			break;

#if i386
		case  TCMEMINFO:
			/*
		 	 * obtain system memory stats
			 *
			 */
			arg->r_meminfo.r_maxmem = maxmem;
			arg->r_meminfo.r_freemem = freemem;
			break;
#endif

		default:
			u.u_error = EINVAL;
	}
}


/*
 * Initialize start up logo.
 * Done at system boot only
 *
 */
ramdinit()
{
	(void)printf(bmgid,machtype);
}


/*
 * Generic kernel print routine 
 * called on internal error in strategy
 * routine (009)
 */
ramdprint(dev,s)
int dev;
char *s;
{
	(void)printf("DANGER: %s on ram disk device %d\n", s, minor(dev));
}
\gux-shar\
else
  echo "will not over write ./ramd.c"
fi
if `test ! -s ./ramd.h`
then
echo "writing ./ramd.h"
cat > ./ramd.h << '\gux-shar\'
/*
 *
 *  @(#)ramd.h	2.5 Copyright (C) B.M.Goodheart 1987, 1888, 1989, 1991 
 *
 *
 *
 *  		      DISCLAIMER OF WARRANTY. 
 *  This software is distributed "as is" and without warranties as to 
 *  performance of merchantability or any other warranties whether expressed 
 *  or implied. In no event shall the author (the copyright holder) be held 
 *  liable for any loss of profit or any other commercial damage resulting 
 *  from the use or misuse of this software, including but not limited to 
 *  special, incidental, consequential or other damages.  The user must 
 *  assume the entire risk of using this software.
 *
 *
 *			LISCENSE AGREEMENT
 *	This software is placed	into the public domain and 
 *	may be copied or distributed freely provided no profit or 
 *	gain is made and is used for personal use only and the code 
 *	as distributed retains all copyright notices in the code. 
 *	This includes any copyright statements in the target
 *	binary and executable code produced from the distributed source. 
 *
 *
 *	                DISTRIBUTION NOTE
 * 	This file contains the code for a RAM disk driver for UNIX System 5.2
 *	and System V.3.	It has been designed specifically for Microport's 
 *	System V/AT iAPX286 and Interactive Systems V/386 i386 systems
 * 	but should work with other PC based System V.? ports with only 
 *	minor modifications, specifically the BUFSEL selector on the 80286.
 *	This driver should work on any V.3 implementation on a PC. 
 *
 *
 *	               IMPORTANT NOTE !!!
 *	Any files or data stored within the ram disks will be 
 *	LOST FOR EVER if the system is brought down for ANY reason.
 *
 *	There are also two other programs distributed associated 
 *	with the driver, they are ramstat(1M) and raminit(1M). 
 *	These are used to control the ram disk driver in user mode 
 *	See also ram(7).
 *
 *	Berny Goodheart (berny at tndsyd.oz@munnari.oz.au)
 *
 */

#define RAM_CLOSED	0
#define RAM_OPEN	1

#define RAMIO		('R'<<8)
#define TCSETRAM	(RAMIO|1)
#define TCDELRAM	(RAMIO|2)
#define TCGETRAM	(RAMIO|3)
#define TCRAMDBG	(RAMIO|4)
#if i386
#define TCMEMINFO	(RAMIO|5)
#endif


#define NRDEVS		4		/* max number of devs	      */

/*
 * NOTE on the i386 machine
 * a block is 4096 bytes
 * on the iAPX286 it is 512 bytes
 *
 * min number of blks/ram disk for a 32k ram disk
 *
 */
#if i386
#define MINRAMSIZ	8
#else
#define MINRAMSIZ	64
#endif

/* union for use by all ramdisk drive ioctl calls */
union r_ramst {
	int 	r_arg;

	/*
	 * Ram device status structure
	 */
	struct {
		int		r_dev[NRDEVS];	/* index to device	*/
		int		r_blks[NRDEVS];	/* physical block count */
		dev_t		r_stat[NRDEVS];	/* open or closed	*/
		int		r_opns[NRDEVS];	/* # of opens	  	*/
		int		r_addr[NRDEVS];	/* mapin memory addr	*/
		dev_t		r_dbg;		/* debug on or off	*/
	}r_rstat;
	
#if i386
	/*
	 * r_meminfo is used to request system wide 
	 * memory information using TCMEMINFO as the ioctl arg
	 * NOTE: not available on 80286
	 *
	 */
	struct {
		ulong		r_maxmem;	/* total system mem     */
		ulong		r_freemem;	/* available mem        */
	} r_meminfo;	
#endif
};


\gux-shar\
else
  echo "will not over write ./ramd.h"
fi
if `test ! -s ./ramd_dfile`
then
echo "writing ./ramd_dfile"
cat > ./ramd_dfile << '\gux-shar\'
ramd	0	4
\gux-shar\
else
  echo "will not over write ./ramd_dfile"
fi
if `test ! -s ./ramd_master`
then
echo "writing ./ramd_master"
cat > ./ramd_master << '\gux-shar\'
ramd	0	ocrwis	bc	ramd	13	14	4 
\gux-shar\
else
  echo "will not over write ./ramd_master"
fi
if `test ! -s ./ramd_mdev`
then
echo "writing ./ramd_mdev"
cat > ./ramd_mdev << '\gux-shar\'
ramd	Iocrwi	iobc	ramd	2	26	1	4	-1
\gux-shar\
else
  echo "will not over write ./ramd_mdev"
fi
if `test ! -s ./ramd_node`
then
echo "writing ./ramd_node"
cat > ./ramd_node << '\gux-shar\'
ramd	ctrlram		c	0
ramd	dsk/ram0	b	0
ramd	dsk/ram1	b	1
ramd	dsk/ram2	b	2
ramd	dsk/ram3	b	3
ramd	rdsk/ram0	c	0
ramd	rdsk/ram1	c	1
ramd	rdsk/ram2	c	2
ramd	rdsk/ram3	c	3
\gux-shar\
else
  echo "will not over write ./ramd_node"
fi
if `test ! -s ./ramd_sdev`
then
echo "writing ./ramd_sdev"
cat > ./ramd_sdev << '\gux-shar\'
ramd	Y	4	0	0	0	0	0	0	0
\gux-shar\
else
  echo "will not over write ./ramd_sdev"
fi
if `test ! -s ./raminit`
then
echo "writing ./raminit"
cat > ./raminit << '\gux-shar\'
:
#
# 
# 
#   @(#)raminit	1.5 Copyright (C) B.M.Goodheart 1987, 1888, 1989, 1991 
# 
# 
#	SV4.0 MOD R. L. Bolin 5-91
# 
#   		      DISCLAIMER OF WARRANTY. 
#   This software is distributed "as is" and without warranties as to 
#   performance of merchantability or any other warranties whether expressed 
#   or implied. In no event shall the author (the copyright holder) be held 
#   liable for any loss of profit or any other commercial damage resulting 
#   from the use or misuse of this software, including but not limited to 
#   special, incidental, consequential or other damages.  The user must 
#   assume the entire risk of using this software.
# 
# 
# 			LISCENSE AGREEMENT
# 	This software is placed	into the public domain and 
# 	may be copied or distributed freely provided no profit or 
# 	gain is made and is used for personal use only and the code 
# 	as distributed retains all copyright notices in the code. 
# 	This includes any copyright statements in the target
# 	binary and executable code produced from the distributed source. 
# 
# 
# 	                DISTRIBUTION NOTE
#  	This file contains the code for a RAM disk driver for UNIX System 5.2
# 	and System V.3.	It has been designed specifically for Microport's 
# 	System V/AT iAPX286 and Interactive Systems V/386 i386 systems
#  	but should work with other PC based System V.? ports with only 
# 	minor modifications, specifically the BUFSEL selector on the 80286.
# 	This driver should work on any V.3 implementation on a PC. 
# 
# 
# 	               IMPORTANT NOTE !!!
# 	Any files or data stored within the ram disks will be 
# 	LOST FOR EVER if the system is brought down for ANY reason.
# 
# 	There are also two other programs distributed associated 
# 	with the driver, they are ramstat(1M) and raminit(1M). 
# 	These are used to control the ram disk driver in user mode 
# 	See also ram(7).
# 
# 	Berny Goodheart (berny at tndsyd.oz@munnari.oz.au)
# 
#
# initialise or remove ram disks ( reads /etc/ramtab )
#
#

trap "echo Interrupt ignored" 1 2 3 15

RAMRC=/etc/ramtab
view=0

if test $# -lt 1 
then
	echo "Usage: raminit -ir [ -v ]"
	exit
fi

if test $# -eq 2
then 
	if [ "$2" != "-v" ]
	then
		echo "Usage: raminit -ir [ -v ]"
		exit
	fi
	view=1
fi

case $1 in
	"-v")
		echo "Usage: raminit -ir [ -v ]"
		exit
		;;
	"-i")

		for x in `/bin/cat $RAMRC | /bin/grep "^\/"`
		do
			block=
			raw=
			size=
			inodes=
			label=
			mnt=
			rnum=

			block=`/bin/echo $x | /usr/bin/awk -F: '{print $1}'`
			raw=`/bin/echo $x | /usr/bin/awk -F: '{print $2}'`
			size=`/bin/echo $x | /usr/bin/awk -F: '{print $3}'`
			inodes=`/bin/echo $x | /usr/bin/awk -F: '{print $4}'`
			label=`/bin/echo $x | /usr/bin/awk -F: '{print $5}'`
			mnt=`/bin/echo $x | /usr/bin/awk -F: '{print $6}'`
			rnum=`/bin/echo $x | /usr/bin/awk -F: '{print $7}'`


			if [ "$rnum" = "" ]
			then
				echo "$0: error in /etc/ramtab, can't continue"
				exit 1
			fi

			# test if the driver is already open
			ramstat -n${rnum} | grep open > /dev/null
			if [ $? = 0 ]
			then
				continue
			fi

			if test -f $mnt/*
			then
				echo "$0: cannot mount on \"$mnt\", directory is not empty"
				continue
			elif test ! -d $mnt
			then
				echo "$0: Directory \"$mnt\" does not exist, entry ignored"
				continue
			else
				:
			fi

			if [ "$block" = "" ]
			then
				echo "$0: Block device not specified, entry ignored"
				continue
			fi

			if [ "$raw" = "" ]
			then
				echo "$0: Raw device not specified, entry ignored"
				continue
			fi

			if [ "$size" = "" ]
			then
				echo "$0: Device size not specified, entry ignored ***"
				continue
			fi

			if [ $view = 1 ]
			then
				echo "Trying for Space for $size * \c"
				if i386
				then
					echo "4k byte blocks"
				else
					echo "1k byte blocks"
				fi
			fi

			# test if we have enough space
			/bin/ramstat -i $size $raw
			if [ $? != 0 ]
			then
				exit
			fi

			echo "Please Wait ...."

			if i386
			then
				size=`expr ${size} \* 4096`
				size=`expr ${size} / 512`
				inodes=`expr ${size} / 10`
			fi

			if [ $view = 1 ]
			then
				echo "Making file system on $block"
				echo "size = $size, inodes = $inodes\n"
			fi

			/etc/mkfs $block $size:$inodes > /dev/null
			if [ "$label" != "" ]
			then
				if [ "$mnt" != "" ]
				then
					j=`basename $mnt`
					if [ $view = 1 ]
					then
						echo "Labeling file system $label\n"
					fi
					/etc/labelit $block ${j} $label > /dev/null
				fi
			fi

			/etc/fsck $block
			if [ "$mnt" != "" ]
			then
				if [ $view = 1 ]
				then
					echo "\nMounting file system on $mnt\n"
				fi
				/etc/mount $block $mnt
			fi
		done
		;;
	"-r")
		ramstat | grep open > /dev/null
		if [ $? != 0 ]
		then
			exit
		fi

		for x in `/bin/cat $RAMRC | /bin/grep "^\/"`
		do
			block=
			raw=
			mnt=
			rnum=

			block=`/bin/echo $x | /usr/bin/awk -F: '{print $1}'`
			raw=`/bin/echo $x | /usr/bin/awk -F: '{print $2}'`
			mnt=`/bin/echo $x | /usr/bin/awk -F: '{print $6}'`
			rnum=`/bin/echo $x | /usr/bin/awk -F: '{print $7}'`

			if [ "$rnum" = "" ]
			then
				echo "$0: error in /etc/ramtab, can't continue"
				exit 1
			fi

			# test if the driver is open
			ramstat -n${rnum} | grep open > /dev/null
			if [ $? != 0 ]
			then
				continue
			fi

			if [ "$block" = "" ]
			then
				echo "$0: Block device not specified, entry ignored ***"
				continue
			fi

			if [ "$raw" = "" ]
			then
				echo "$0: Raw device not specified, entry ignored ***"
				continue
			fi

			if [ "$mnt" = "" ]
			then
				/bin/ramstat -r $block $raw
			else
				if /etc/umount $block 
				then
					/bin/ramstat -r $block $raw
				fi
			fi
		done
		;;
	*) /bin/echo "$0: illegal option $1" ;;
esac

\gux-shar\
else
  echo "will not over write ./raminit"
fi
if `test ! -s ./raminit.1m`
then
echo "writing ./raminit.1m"
cat > ./raminit.1m << '\gux-shar\'
.TH RAMINIT 1M
.SH NAME
.B raminit
\- memory resident disk interface control script
.SH SYNOPSIS
.B raminit -ri [ -v ]
.SH DESCRIPTION
.B Raminit
is the control script program used to configure the Ram disk device.
It reads the file
.B /etc/ramtab
to find out how to configure the ram disks.
.PP
The ram disk interface allows up to 4 ram disks to be resident in
memory at any one time. 
.PP
.B Raminit
sets up the ram disks via 
.B /bin/ramstat
and then runs 
.B mkfs(1M)
and
.B fsck(1M)
to create the file systems and check them before using
.B mount(1M)
to mount them accordingly.
.PP
The option 
.B -i 
is used to initiate the ram disks, while the
option 
.B -r 
is used to delete them, 
.B -v 
is an optional
parameter which turns verbose mode on (default is off).
.PP
Deleting the ram disks frees up memory allowing it to be used 
again by user programs.
.PP
The structure of the file
.B /etc/ramtab 
is as follows:
.P
.TP 16
.B field 1
The Block device path name.
.br
.TP 16
.B field 2
The Raw device path name.
.br
.TP 16
.B field 3
The size in blocks of the ram disk.
.br
.TP 16
.B field 4
The number of inodes for the new file system.
.br        
.TP 16
.B field 5
File system label.
.br
.TP 16
.B field 6
The name of the empty directory to mount the file system on to.
.br
.TP 16
.B field 7
The minor number of the ramdisk associated with the new file system.
.PP
Each field is separated by a ':' character.
.SH EXAMPLES
.PP
.ti+6
/dev/dsk/ram0:/dev/rdsk/ram0:750:200:tmp:/tmp:0:
.PP
This 
.B ramtab
entry is used by
.B raminit
to create a ram disk using the block special file
.B /dev/dsk/ram0
and the character special file 
.B /etc/rdsk/ram0,
of 750 physical blocks of memory, construct a file
sytem with 200 inodes and label it tmp, mount the new
file system onto /tmp, using minor device 0.
.SH FILES
/dev/ctrlram
.br
/dev/rdsk/ram?
.br
/dev/dsk/ram?
.br
/dev/console
.br
/etc/ramtab
.br
/bin/ramstat
.SH SEE ALSO
fs(4),mkfs(1M),fsck(1M),mount(1M),labelit(1M),ramstat(1M)
.SH AUTHOR
B.M.Goodheart 

\gux-shar\
else
  echo "will not over write ./raminit.1m"
fi
if `test ! -s ./ramrc.d`
then
echo "writing ./ramrc.d"
cat > ./ramrc.d << '\gux-shar\'


#initialise and install the ram disks

/etc/raminit -i
\gux-shar\
else
  echo "will not over write ./ramrc.d"
fi
if `test ! -s ./ramstat.1m`
then
echo "writing ./ramstat.1m"
cat > ./ramstat.1m << '\gux-shar\'
.TH RAMSTAT 1M
.SH NAME
.B ramstat
\- memory resident disk interface control
.SH SYNOPSIS
.B ramstat 
.br
.B ramstat -n#
.br
.B ramstat -m
.br
.B ramstat -d
.br
.B ramstat -i blocks  char_special
.br
.B ramstat -r block_special char_special
.SH DESCRIPTION
.B Ramstat
is the control program used to configure or get information from
the kernel about the Ram disk devices.
.PP
The meaning of the options are:
.br
.PP
.TP 8
.B -n#
Display statistics on the standard output of a ramdisk,
where '#' represents the minor number associated with the driver,
.TP 8
.B -m
Display statistics on the standard output of current
available memory resources. This option is not available on
80286 processors.
.TP 8
.B -d
Toggles debug mode.
.TP 8
.B -i
This parameter takes a further two arguments; the
block number being the number of physical blocks
to configure the ram disk with and the ram disk 
raw interface path name.
.PP
.RS 8
This option is used to configure the ram disk 
before building a file system on it.
.RE
.TP 8
.B -r
This parameter also requires a further two 
arguments; the path names of the raw and block 
interface files. This option is used to delete 
the ram disk from existence freeing up memory. 
This option will cause ramstat to fail if 
the ram disk contains a currently mounted 
file system.
.PP
If invoked with no parameters then 
.I ramstat 
will display status
information about all of the ramdisks on the standard output.
.PP
The meaning of the column headings are as follows:
.PP
RAM       The ramdisk minor number.
.PP
BLOCKS    The number of physical blocks the ram disk 
          was configured with.
.PP
STATE     The current state of the ram disk open or closed.
.PP
OPENS     The number of processes currently holding the
          ramdisk open.
.PP
ADDR      The physical base address in Hex of the ram disk
          in memory.
.PP
The state of the debug mode is also displayed.
.PP
It is better to use the script 
.I raminit
to invoke the -i and -r options. Raminit invokes 
.I ramstat
in the long run any way. If 
.I ramstat
is invoked in this way
it is possible to enter a single line in the /etc/rc file
to configure the ram disks at system boot time.
.SH FILES
/dev/ctrlram
.br
/dev/rdsk/ram?
.br
/dev/dsk/ram?
.br
/dev/console
.SH SEE ALSO
fs(4),mkfs(1M),fsck(1M),volcopy(1M),raminit(1M)
.SH BUGS
On the System V.4.0 version, the -m option gives an incorrect report 
(0 is given). This seems to be a BUG in SV4.0 (sysinfo.h).
.SH AUTHOR
B.M.Goodheart
\gux-shar\
else
  echo "will not over write ./ramstat.1m"
fi
if `test ! -s ./ramstat.c`
then
echo "writing ./ramstat.c"
cat > ./ramstat.c << '\gux-shar\'
/*
 *
 *  @(#)ramstat.c	1.6 Copyright (C) B.M.Goodheart 1987, 1888, 1989, 1991 
 *
 *
 *
 *  		      DISCLAIMER OF WARRANTY. 
 *  This software is distributed "as is" and without warranties as to 
 *  performance of merchantability or any other warranties whether expressed 
 *  or implied. In no event shall the author (the copyright holder) be held 
 *  liable for any loss of profit or any other commercial damage resulting 
 *  from the use or misuse of this software, including but not limited to 
 *  special, incidental, consequential or other damages.  The user must 
 *  assume the entire risk of using this software.
 *
 *
 *			LISCENSE AGREEMENT
 *	This software is placed	into the public domain and 
 *	may be copied or distributed freely provided no profit or 
 *	gain is made and is used for personal use only and the code 
 *	as distributed retains all copyright notices in the code. 
 *	This includes any copyright statements in the target
 *	binary and executable code produced from the distributed source. 
 *
 *
 *	                DISTRIBUTION NOTE
 * 	This file contains the code for a RAM disk driver for UNIX System 5.2
 *	and System V.3.	It has been designed specifically for Microport's 
 *	System V/AT iAPX286 and Interactive Systems V/386 i386 systems
 * 	but should work with other PC based System V.? ports with only 
 *	minor modifications, specifically the BUFSEL selector on the 80286.
 *	This driver should work on any V.3 implementation on a PC. 
 *
 *
 *	               IMPORTANT NOTE !!!
 *	Any files or data stored within the ram disks will be 
 *	LOST FOR EVER if the system is brought down for ANY reason.
 *
 *	There are also two other programs distributed associated 
 *	with the driver, they are ramstat(1M) and raminit(1M). 
 *	These are used to control the ram disk driver in user mode 
 *	See also ram(7).
 *
 *	Berny Goodheart (berny at tndsyd.oz@munnari.oz.au)
 *
 * The user program /etc/ramstat is used to initialise the RAM disk
 *
 *		-i	Initialise the RAM disk.
 *		-r	Delete and remove the RAM disk and all its contents
 *		-d	toggle debug mode on or off
 *		-n#	display stats of ram disk '#'
 *		-m	get system memory info (i386) only
 *
 *
 *	5-10-91 - SV4.0 MOD - R. L. Bolin @ gatech!sbmsg1!bsts00!rlb
 *		  See defines for SV4
 */


#ifdef SV4
static char *bmgid = "@(#)ramstat.c	1.6 (SV4.0) Copyright (C) Berny Goodheart 5/20/91";
#else
static char *bmgid = "@(#)ramstat.c	1.6 Copyright (C) Berny Goodheart 5/20/91";
#endif
#include <sys/types.h>
#include <stdio.h>
#include <ctype.h>
#include <signal.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ramd.h>

static int size;
static int fd;
char devnam[128];
extern int errno;
static int ramnum;

union r_ramst state;

#if i386
#define pdetophys(x)	(x * 4096)
#endif

#ifdef SV4
static void
_trap(sig)
int sig;
#else
static void
_trap()
#endif
{
	(void) signal(SIGINT,_trap);
	if(fd > 0)
		close(fd);
	printf("Aborted\n");
	exit(0);
}

main(argc,argv)
int argc;
char *argv[];
{

	(void) signal(SIGINT,_trap);
	ramnum = -1;

	/*
 	 * Allow users to get stats
	 */
	if(argc != 1)
		setuid(getuid());

	if((fd = open("/dev/ctrlram",O_WRONLY)) == -1){
		perror("/dev/ctrlram");
		exit(1);
	} 

	if(argc == 1) {
		ramstat(fd,TCGETRAM);
		exit(0);
	}


	if(argv[1][0] != '-')
		usage();

	switch (argv[1][1]) {
#if i386
		case 'm':
			if(argc != 2)
				usage();
			ramstat(fd,TCMEMINFO);
			break;
#endif
		case 'n':
			if(isdigit(argv[1][2])) {
				ramnum = atoi(&argv[1][2]);
				ramstat(fd,TCGETRAM);
			} else usage();
			break;
		case 'd':
			if(argc != 2)
				usage();
			ramstat(fd,TCRAMDBG);
			break;
		case 'r':
			if(argc != 4)
				usage();
			close(fd);
			if((fd = open(argv[2],O_WRONLY)) == -1){
				perror(argv[2]);
				exit(1);
			} 
			close(fd);
			if((fd = open(argv[3],O_WRONLY)) == -1){
				perror(argv[3]);
				exit(1);
			}
			strcpy(devnam,argv[3]); 
			if(umount(argv[2]) == -1) {
				if(errno != EINVAL) {
					perror(argv[2]);
					exit(1);
				}
			}
			ramstat(fd,TCDELRAM);
			break;
		case 'i':
			if(argc != 4)
				usage();
			close(fd);
			if((fd = open(argv[3],O_WRONLY)) == -1){
				perror(argv[3]);
				exit(1);
			}
			strcpy(devnam,argv[3]); 
			if((size = atoi(argv[2])) < 20) {
				fprintf(stderr,"ramstat: illegal block size\n");
				exit(1);
			}
			ramstat(fd,TCSETRAM);
			break;
		default :
			usage();
	}
	close(fd);
	exit(0);
}

ramstat(fd,mode)
int fd, mode;
{
	int x,m;
	
	switch(mode) {
#if i386
		case TCMEMINFO:
			if((x = ioctl(fd,TCMEMINFO,&state)) != -1)
				printf("maxmem %ld\nfreemem %ld\n",
					pdetophys(state.r_meminfo.r_maxmem),
					pdetophys(state.r_meminfo.r_freemem));
			break;
#endif
		case TCDELRAM:
			if((x = ioctl(fd,TCDELRAM,0)) != -1)
				printf("Ram disk %s closed\n",devnam);
			break;
		case TCSETRAM:
			state.r_arg = size;
			if((x = ioctl(fd,TCSETRAM,&state)) != -1) 
				printf(
				"\nRam disk (%s) initialized (%d Physical Blocks)\n\n"
					,devnam,size);
			break;
		case TCRAMDBG:
			if((x = ioctl(fd,TCRAMDBG,&state)) != -1) 
				printf("Ram disk debug mode %s\n",
					state.r_arg == 0 ? "OFF" : "ON");
			break;
		case TCGETRAM:
			if((x = ioctl(fd,TCGETRAM,&state)) != -1) {
			if(ramnum == -1)
				printf("\n   RAM	BLOCKS	STATE	OPENS	ADDR\n");
			for(x = 0; x < NRDEVS;x++) {
				if(ramnum != -1 && ramnum != x)
					continue;
				printf(
				"   %d	%d	%s	%d	0x%x%c"
				,state.r_rstat.r_dev[x]
				,state.r_rstat.r_blks[x]
				,state.r_rstat.r_stat[x]
					== RAM_OPEN ? "open" : "closed"
				,(state.r_rstat.r_opns[x] 
					== 0 ? 0 : state.r_rstat.r_opns[x] -1)
				,state.r_rstat.r_addr[x]
				,(ramnum == -1 ? '\n' : ' '));
			}
			if(state.r_rstat.r_dbg != 0) {
				if(ramnum == -1)
					printf("\n  ");
				printf(" Debug ON");
			}
			putchar('\n');
			}/* if */

	}
	if(x < 0) {
		perror("ramstat");
		exit(1);
	}
	close(fd);
}


	
usage()
{
	fprintf(stderr,"Usage: ramstat\n"); 
	fprintf(stderr,"       ramstat -d\n");
	fprintf(stderr,"       ramstat -n#\n");
#if i386
	fprintf(stderr,"       ramstat -m\n");
#endif
	fprintf(stderr,"       ramstat -r  block_special  char_special\n");
	fprintf(stderr,"       ramstat -i  blocks  char_special\n");
	exit(1);
}

\gux-shar\
else
  echo "will not over write ./ramstat.c"
fi
if `test ! -s ./ramtab`
then
echo "writing ./ramtab"
cat > ./ramtab << '\gux-shar\'
#
# This file contains table information for the ram disk 
# configuration program called "raminit".
#
# See manual entries ramstat(1M), raminit(1M), ram(7)
#
# block_dev:char_dev:size:inodes:label:mount directory:driver minor
#
# NOTE: the 80386 uses 4096 bytes in a block so size
#	is n * 4096. The 80286 uses 512 byte blocks
#

# inodes and label are optional

/dev/dsk/ram0:/dev/rdsk/ram0:500:150:tmp:/tmp:0:
#/dev/dsk/ram1:/dev/rdsk/ram1:250:50:vbin:/vbin:1:
#/dev/dsk/ram0:/dev/rdsk/ram0:1500:100:tmp:/tmp:0:
#/dev/dsk/ram1:/dev/rdsk/ram1:500:100:ram1:/ram:1:
#/dev/dsk/ram2:/dev/rdsk/ram2:500::::2:
#/dev/dsk/ram3:/dev/rdsk/ram3:500::::3:
\gux-shar\
else
  echo "will not over write ./ramtab"
fi
echo "Finished archive 1 of 1"
# if you want to concatenate archives, remove anything after this line
exit

.===========================================================================.
|   ACSnet: berny at tndsyd.oz       UUCP: uunet!munnari.oz!tndsyd.oz.au!berny |
| INTERNET: berny at tndsyd.oz.au  DOMAIN: goodheart_berny at tandem.com          |
|   PSMAIL: smtpgate @comm(berny at tndsyd.oz@munnari.oz.au)                   |
TANDEM Computers Incorporated 76 Berry St, North Sydney, NSW, 2060, Australia



More information about the Comp.unix.sysv286 mailing list