File:  [MW Coherent from dump] / coherent / b / kernel / io.386 / rm.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Wed May 29 04:56:37 2019 UTC (7 years ago) by root
Branches: MarkWilliams, MAIN
CVS tags: relic, HEAD
coherent

/* (-lgl
 * 	COHERENT Device Driver Kit version 1.2.0
 * 	Copyright (c) 1982, 1991 by Mark Williams Company.
 * 	All rights reserved. May not be copied without permission.
 -lgl) */
/*
 * Block or character device RAM disk driver.
 */

#include	<sys/coherent.h>
#include	<sys/buf.h>
#include	<errno.h>
#ifndef _I386
#include	<sys/uproc.h>
#include	<sys/devices.h>
#endif
#include	<sys/seg.h>
#include	<sys/con.h>
#include	<sys/inode.h>
#include	<sys/stat.h>

#if _I386
/*
 * Patchable variables for 386.
 * Starting addresses in kernel data and size for each ram disk.
 */
int	RAM0=0x88000000;
int	RAMSIZE=0x800000;
#define RAM1	(RAM0 + RAMSIZE)
#endif

/*
 * Minor number encoding: dsssssss
 * d       drive number (0 or 1)
 * sssssss allocation size: 0 to free, 1-127 allocsize (n*ASIZE*BSIZE bytes)
 */
#define	rm_drive(dev)	(minor(dev) >> 7)
#define	rm_asize(dev)	(minor(dev) & 0x7F)
#define	ASIZE		128	/* allocation chunk size in blocks (64KB) */
#define NUM_RM		2	/* number of ram disks */
				/* - tied to dev encoding (see above) */
#ifdef _I386
#define	RMMAJ		8	/* major # for driver */
#endif

int	nulldev();
int	nonedev();
int	rmload();
int	rmuload();
int	rmopen();
int	rmclose();
int	rmread();
int	rmwrite();
int	rmblock();

CON	rmcon	= {
	DFBLK|DFCHR,
#ifndef _I386
	RM_MAJOR,
#else
	RMMAJ,
#endif
	rmopen,			/* Open */
	rmclose,		/* Close */
	rmblock,		/* Block */
	rmread,			/* Read */
	rmwrite,		/* Write */
	nonedev,
	nulldev,
	nulldev,
	rmload,			/* Load */
	rmuload			/* Unload */
};

typedef struct rm {
#ifndef _I386
	fsize_t	rm_size;	/* Size in allocation chunks */
	paddr_t	rm_paddr;	/* Physical base of ram disc segment */
	SEG	*rm_segp;	/* Segment pointer of ram device */
#else
	off_t	rm_size;	/* Size in allocation chunks */
	SR	rm_sr;
#endif
	BUF	rm_buf;		/* Static buffer for raw requests */
	int	rm_nopen;	/* Open count to avoid blowups */
} RM;
static	RM	rm[NUM_RM];

/*
 * Load.
 */
static
rmload()
{
}

/*
 * Unload.
 * Release the allocated buffers.
 */
static
rmuload()
{
	int i;

	for (i = 0; i < NUM_RM; i++){
#ifndef _I386
		if (rm[i].rm_size != 0)
			sfree(rm[i].rm_segp);
#else
		if (rm[i].rm_size != 0) {
			unload(&rm[i].rm_sr);
			sfree(rm[i].rm_sr.sr_segp);
		}
#endif
	}
}

/*
 * Open.
 * Allocate on the first call.
 * Increment the open count.
 */
static
rmopen(dev, mode) dev_t dev; int mode;
{
	register RM *rmp;
#ifndef _I386
	register fsize_t asize, osize;
	register SEG *segp;
#else
	register off_t asize, osize;
#endif

	rmp = &rm[rm_drive(dev)];
	asize = rm_asize(dev);
	osize = rmp->rm_size;

	/* Fail on read before creation or bogus size. */
	if ((mode == IPR && osize == 0)
	 || (asize != 0 && osize != 0 && asize != osize)
	 || (asize == 0 && osize == 0)) {
		SET_U_ERROR( ENXIO,
			"can not read ram disk yet or bogus size" );
		return;
	}

#ifdef _I386
	if (ASIZE*BSIZE*asize > RAMSIZE) {
		SET_U_ERROR( ENOMEM, "Ram disk too big" );
		return;
	}
#endif

	/*
	 * Allocate as required.
	 * Ignore case asize==0 && osize!=0, handled by rmclose().
	 * If asize!=0 && asize==osize, just bump the open count.
	 */
	if (asize != 0 && osize == 0) {
#ifndef _I386
		segp = rmp->rm_segp = salloc((fsize_t)ASIZE*BSIZE*asize,
			SFSYST|SFNSWP|SFNCLR|SFHIGH);
		if (segp == NULL) {
			SET_U_ERROR( ENOMEM,
				"can not allocate segment for ram disk" );
			return;
		}
#else
		rmp->rm_sr.sr_segp =
		    salloc((off_t)ASIZE*BSIZE*asize, SFSYST|SFNSWP|SFNCLR);
		if (rmp->rm_sr.sr_segp == NULL) {
			SET_U_ERROR( ENOMEM,
				"can not allocate segment for ram disk" );
			return;
		}
#endif
		rmp->rm_size = asize;
#ifndef _I386
		rmp->rm_paddr = segp->s_paddr;
		rmp->rm_nopen = 0;
		pclear(rmp->rm_paddr, 1024L);	/* clear 1st 2 blocks */
#else
		rmp->rm_sr.sr_base = rm_drive(dev)==0 ? RAM0 : RAM1;
		rmp->rm_sr.sr_size = rmp->rm_sr.sr_segp->s_size;
		doload(&rmp->rm_sr);
#endif
	}
	rmp->rm_nopen++;
}

/*
 * Close.
 * Decrement the open count.
 * Release the allocated buffer if minor number is 0.
 */
static
rmclose(dev) dev_t dev;
{
	register RM *rmp;
#ifndef _I386
	register fsize_t asize, osize;
#else
	register off_t asize, osize;
#endif

	rmp = &rm[rm_drive(dev)];
	asize = rm_asize(dev);
	osize = rmp->rm_size;

	if (osize == 0
	 || (asize != 0 && asize != osize)
	 || rmp->rm_nopen == 0) {
		u.u_error = ENXIO;
		return;
	}
	rmp->rm_nopen--;
	if (asize == 0) {
		if (rmp->rm_nopen != 0) {
#ifndef _I386
			u.u_error = EDBUSY;
#else
			u.u_error = EBUSY;
#endif
			return;
		}
#ifndef _I386
		sfree(rmp->rm_segp);
#else
		unload(&rmp->rm_sr);
		sfree(rmp->rm_sr.sr_segp);
#endif
		rmp->rm_size = 0;
	}
}

static
rmblock(bp) register BUF *bp;
{
#ifndef _I386
	paddr_t base;
	register fsize_t asize, osize;
#else
	caddr_t base;
	register off_t asize, osize;
#endif
	dev_t dev;
	register RM *rmp;

	dev = bp->b_dev;
	rmp = &rm[rm_drive(dev)];
	asize = rm_asize(dev);
	osize = rmp->rm_size;
	if (osize == 0 || asize != osize)
#ifndef _I386
		bp->b_flag |= BFERR;
	/*
	 * Make sure last block requested is within range of device.
	 */	
	else if ((bp->b_bno + bp->b_count/BSIZE - 1) >= asize*ASIZE)
		bp->b_flag |= BFERR;
#else
		u.u_error = ENXIO;
	else if (bp->b_bno >= asize*ASIZE)
		u.u_error = EIO;
#endif
	else {
#ifndef _I386
		base = rmp->rm_paddr + (paddr_t)bp->b_bno * BSIZE;
#else
		base = rmp->rm_sr.sr_base + (paddr_t)bp->b_bno * BSIZE;
#endif
		if (bp->b_req == BREAD)
#ifndef _I386
			plrcopy(base, bp->b_paddr, (fsize_t)bp->b_count);
#else
			dmaout(bp->b_count, bp->b_paddr, base);
#endif
		else
#ifndef _I386
			plrcopy(bp->b_paddr, base, (fsize_t)bp->b_count);
#else
			dmain(bp->b_count, bp->b_paddr, base);
#endif
	}
	bdone(bp);
}

/*
 * The read routine calls the common raw I/O processing code,
 * using a static buffer header in the driver.
 */
static
rmread(dev, iop) register dev_t dev; IO *iop;
{
	register BUF *bufp;

	bufp = &rm[rm_drive(dev)].rm_buf;
	ioreq(bufp, iop, dev, BREAD, BFIOC|BFRAW);
}

/*
 * The write routine is just like the read routine,
 * except that the function code is write instead of read.
 */
static
rmwrite(dev, iop) register dev_t dev; IO *iop;
{
	register BUF *bufp;

	bufp = &rm[rm_drive(dev)].rm_buf;
	ioreq(bufp, iop, dev, BWRITE, BFIOC|BFRAW);
}

/* end of rm.c */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.