ramdisk driver for 2.9

Keith Packard keith at motel6.UUCP
Mon Nov 18 21:28:59 AEST 1985


I have just completed a driver that makes a segment of memory into a 
pseudo disk drive.  It was rather simple to do but I thought that
someone might like to see just how it was done.  The device driver
itself is very short and straight forward.  The remaining modifications
were also fairly straight forward if you know where to put the hooks in.

The description that follows is about the 2.9 distribution that I
received from berkeley about a year or so ago.  It can be applied to
the bostic 2.9 distribution although I am still working on getting
that system running (I'm bringing up the networking code on my
11/73 - more details about that when it works) and don't have that
code on-line (I'm hacking on that on another computer).

The allocation of the block of memory occurs in the startup code along
with the allocation for disk buffers and clists.  The constant NRAM
specifies how many 512-byte blocks to allocate for the ramdisk and is
defined in "ram.h":

********ram.h*********
/*
 *	number of blocks for a ram disk
 */

# define	NRAM	512

********EOF***********

accordingly, include ram.h in machdep.c and add a declaration at the
top of startup:

****machdep.c*****
  /*
   * Machine dependent startup code
   */
  startup()
  {
  	register memaddr i, freebase;
+ #if NRAM > 0
+ 	unsigned	ramstart;
+ #endif
  	extern	end;

*****

then put in the allocation code:

*****

  #ifdef	UCB_CLIST
  #define	C	(nclist * sizeof(struct cblock))
  	if ((clststrt = malloc(coremap, btoc(C))) == 0)
  		panic("clists");
  	maxmem -= btoc(C);
  	clstaddr = ((ubadr_t) clststrt) << 6;
  #undef	C
  #else
  	clstaddr = (ubadr_t) &cfree;
  #endif	UCB_CLIST
  
+ #if	NRAM > 0
+ #define C	(NRAM << 3)
+ 	if ((ramstart = malloc (coremap, C)) == 0)
+ 		panic ("ramdisk");
+ 	maxmem -= C;
+ 	raminit (ramstart);
+ #undef 	C
+ #endif	NRAM
  	
  #if	defined(PROFILE) && !defined(ENABLE34)
  	maxmem -= msprof();
  #endif	defined(PROFILE) && !defined(ENABLE34)

******

Then fix c.c to include a ramdisk entry.  Your c.c will probably
be different as I have also written a driver for my DTC/Xebec
winchester controller which precedes the ramdisk entries.

******* c.c ******

+ #include	"ram.h"
+ #if	NRAM > 0
+ int	ramstrategy(), ramread(), ramwrite();
+ extern	struct buf	ramtab;
+ #define ramopen		nulldev
+ #define ramclose	nulldev
+ #define _ramtab		&ramtab
+ #else
+ #define ramopen		nodev
+ #define ramclose	nodev
+ #define ramstrategy	nodev
+ #define ramread		nodev
+ #define ramwrite	nodev
+ #define _ramtab		((struct buf *) NULL)
+ #endif NRAM

  #include	"rl.h"
  #if	NRL > 0
  int	rlstrategy(), rlread(), rlwrite();
  extern	struct	buf	rltab;
  #define	rlopen		nulldev
  #define	rlclose		nulldev
  #define	_rltab		&rltab
  #else
  #define	rlopen		nodev
  #define	rlclose		nodev
  #define	rlstrategy	nodev
  #define	rlread		nodev
  #define	rlwrite		nodev
  #define	_rltab		((struct buf *) NULL)
  #endif	NRL

********** bdevsw ***********

  #if NRX > 0
  	rxopen,		rxclose,	rxstrategy,
  	nulldev,	_rxtab,		/* rx = 10 */
  #else
  	rx2open,	rx2close,	rx2strategy,
  	nulldev,	_rx2tab,	/* rx2 = 10 */
  #endif
  
  	xeopen,		xeclose,	xestrategy,
  	nulldev,	_xetab,		/* xe = 11 */
  	
+ 	ramopen,	ramclose,	ramstrategy,
+ 	nulldev,	_ramtab,	/* ram = 12 */
  };
************ cdevsw *************
  
  #if NRX > 0
  	rxopen,		rxclose,	rxread,		rxwrite,
  	rxioctl,	nulldev,	0,		/* rx = 22 */
  #else
  	rx2open,	rx2close,	rx2read,	rx2write,
  	rx2ioctl,	nulldev,	0,		/* rx2 = 22 */
  #endif
  
  	xeopen,		xeclose,	xeread,		xewrite,
  	nodev,		nulldev,	0,		/* xe = 23 */
  
+ 	ramopen,	ramclose,	ramread,	ramwrite,
+ 	nodev,		nulldev,	0,		/* ram = 24 */
  };

**********************

Now install the driver in ../dev/ram.c:

*************** ram.c ************
/*
 *	SCCS id	@(#)ram.c	2.1 (motel6)	11/18/85
 */

/*
 *  ram disk driver
 */

#include "ram.h"
#if	NRAM > 0
#include "param.h"
#include <sys/buf.h>
#include <sys/dir.h>
#include <sys/user.h>
#include <sys/systm.h>
#include <sys/conf.h>

struct buf	rrambuf;

struct buf	ramtab;
/*
 *	starting click of ram buffer
 */
unsigned	ramclick;
# define bltocl(b)	(((b)<<3) + ramclick)

ramattach(addr, unit)
char *addr;
{
	return(1);
}

raminit (base)
unsigned base;
{
	ramclick = base;
}

ramstrategy(bp)
register struct	buf *bp;
{
	int	ramc, bufc, count;

	if (!ramclick) {
		goto bad;
	}
	if(bp->b_blkno + (bp->b_bcount>>BSHIFT) >= NRAM) {
		if((bp->b_blkno == NRAM) && (bp->b_flags & B_READ))
			bp->b_resid = bp->b_bcount;
		else {
bad:			;
			bp->b_error = ENXIO;
			bp->b_flags |= B_ERROR;
		}
		iodone(bp);
		return;
	}
	/*
	 *	just copy the whole block using
	 *	the l.s copy routine, if possible
	 */
	if ((bp->b_un.b_addr & 63) || (bp->b_bcount & 63)) {
		goto bad;
	}
	bufc = ((bp->b_un.b_addr >> 6) & 01777);
	bufc += bp->b_xmem << 10;
	ramc = bltocl (bp->b_blkno);
	count = bp->b_bcount >> 6;
	if (bp->b_flags & B_READ)
		copy (ramc, bufc, count);
	else
		copy (bufc, ramc, count);
	iodone (bp);
}

ramread(dev)
dev_t	dev;
{
	physio(ramstrategy, &rrambuf, dev, B_READ);
}

ramwrite(dev)
dev_t	dev;
{
	physio(ramstrategy, &rrambuf, dev, B_WRITE);
}
#endif	NRAM

***************EOF****************

that should be it.  make a new kernel, boot it and make the
devices in /dev.  Note that the raw device does not support
completely general I/O - it is very possible to break things
doing raw i/o.  I suggest never using the raw device.

keith packard
tektronix!reed!motel6!keith



More information about the Comp.bugs.2bsd mailing list