ramdisk1of1 - RAM Disk Driver for UNIX on the PC
Berny Goodheart
berny at tndsyd.oz.au
Thu Apr 11 20:41:16 AEST 1991
This is a ram disk for UNIX System V.2 or UNIX System V.3 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
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.
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.
------------------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:
# ./ram.7
# ./ram.c
# ./ram.h
# ./raminit
# ./raminit.1m
# ./ramstat.1m
# ./ramstat.c
# ./ramtab
# ./README
#
if `test ! -s ./ram.7`
then
echo "writing ./ram.7"
cat > ./ram.7 << '\gux-shar\'
.TH RAM 7
.SH NAME
.B ram
\- 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 ./ram.7"
fi
if `test ! -s ./ram.c`
then
echo "writing ./ram.c"
cat > ./ram.c << '\gux-shar\'
/*
*
* @(#)ram.c 2.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)
*
* 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.
*/
static char *bmgid =
"RAM disk 2.6-(%s) Copyright (C) Berny Goodheart 4/11/91\n";
#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/ram.h> /* header file for this driver */
#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
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
*
*/
ramopen(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);
}
ramclose(dev)
{
ROPEN(dev) = 0; /* only called on last close */
}
/*
* strategy routine is called by both character and block
* drivers to do the I/O.
*/
ramstrategy(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)
*
*/
#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);
}
/*
* ramread
*
* Uses ramstrategy for RAW I/O
*
*/
ramread(dev)
int dev;
{
(void)physio(ramstrategy,NULL,dev,B_READ);
}
/*
* ramwrite
*
* Uses ramstrategy for RAW I/O
*
*/
ramwrite(dev)
int dev;
{
(void)physio(ramstrategy,NULL,dev,B_WRITE);
}
/*
* user interface to I/O control
*
*/
ramioctl(dev, cmd, arg)
int dev, cmd;
union r_ramst *arg;
{
register x;
int intlevel;
#if i386
caddr_t ptalloc(); /* page table allocation routine */
/*
* 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
if((RADDR(dev) = ptalloc(RSIZE(dev),
PHYSCONTIG|NOSLEEP)) == 0) {
#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() does not return anything
*/
(void)uptfree(RADDR(dev),RSIZE(dev));
#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
*
*/
raminit()
{
(void)printf(bmgid,machtype);
}
/*
* Generic kernel print routine
* called on internal error in strategy
* routine (009)
*/
ramprint(dev,s)
int dev;
char *s;
{
(void)printf("%s on ram disk device %d\n", s, minor(dev));
}
\gux-shar\
else
echo "will not over write ./ram.c"
fi
if `test ! -s ./ram.h`
then
echo "writing ./ram.h"
cat > ./ram.h << '\gux-shar\'
/*
*
* @(#)ram.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 ./ram.h"
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
#
#
#
# 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} / 1024`
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 ./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 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.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)
*
* 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
*
*
*/
static char *bmgid = "@(#)ramstat.c 1.5 Copyright (C) Berny Goodheart 4/11/91";
#include <sys/types.h>
#include <stdio.h>
#include <ctype.h>
#include <signal.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ram.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
trap()
{
signal(SIGINT,trap);
if(fd > 0)
close(fd);
printf("Aborted\n");
exit(0);
}
main(argc,argv)
int argc;
char *argv[];
{
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
if `test ! -s ./README`
then
echo "writing ./README"
cat > ./README << '\gux-shar\'
This is a ram disk for UNIX System V.2 or UNIX System V.3 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
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.
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.
\gux-shar\
else
echo "will not over write ./README"
fi
echo "Finished archive 1 of 1"
# if you want to concatenate archives, remove anything after this line
exit
More information about the Comp.unix.sysv286
mailing list