2.11BSD/sys/pdp/ram.c
/*
* ISR 'ramdisk' driver.
* This driver implements a 'ram disk' in main memory.
*
* For the block device, the driver works by remapping buffer header
* addresses and simply returning. This way the buffer copy is done only
* once. It is faster than any mass storage device in access time and
* transfer time (both are immediate) and consumes less cpu time in the
* driver than most.
*
* Gregory Travis, Institute for Social Research, September 1984
* Mucked about, KB, March 1987.
* Remucked and stomped, Casey Leedom, August 1987.
*/
#include "ram.h"
#if NRAM > 0
#include "param.h"
#include "../machine/seg.h"
#include "buf.h"
#include "user.h"
#include "conf.h"
#include "map.h"
#include "systm.h"
#include "dk.h"
#ifdef UCB_METER
static int ram_dkn = -1; /* number for iostat */
#endif
u_int ram_size = NRAM; /* (patchable) ram disk size */
memaddr ram_base; /* base of ram disk area */
/*
* Allocate core for ramdisk(s)
*/
size_t
raminit()
{
if (ram_size) {
if (ram_base = malloc(coremap, ram_size*btoc(NBPG))) {
#ifdef UCB_METER
dk_alloc(&ram_dkn, 1, "ram", 0L);
#endif
return(ram_size*btoc(NBPG));
}
printf("ram: nospace\n");
}
return(0);
}
ramopen(dev)
dev_t dev;
{
if (minor(dev) || !ram_base)
return (ENXIO);
return (0);
}
ramstrategy(bp)
register struct buf *bp;
{
register memaddr ramaddr;
if (!ram_base) {
printf("ram: not allocated\n");
bp->b_error = ENXIO;
bp->b_flags |= B_ERROR;
goto done;
}
if(bp->b_blkno < 0 ||
((bp->b_blkno + ((bp->b_bcount+(NBPG-1)) >> PGSHIFT)) > ram_size)) {
bp->b_error = EINVAL;
bp->b_flags |= B_ERROR;
goto done;
}
#ifdef UCB_METER
if (ram_dkn >= 0) {
dk_xfer[ram_dkn]++;
dk_wds[ram_dkn] += bp->b_bcount>>6;
}
#endif
ramaddr = ram_base + bp->b_blkno * btoc(NBPG);
if (bp->b_flags & B_PHYS)
ramstart(ramaddr, bp);
else if (bp->b_flags & B_READ) {
#ifdef DIAGNOSTIC
if(bp->b_flags & B_RAMREMAP)
panic("ram: remap!");
#endif
bp->b_flags |= B_RAMREMAP; /* block read (sic) */
bp->b_un.b_addr = (caddr_t)(ramaddr << 6);
bp->b_xmem = (ramaddr >> 10) & 077;
} else
if ((bp->b_flags & B_RAMREMAP) == 0)
ramstart(ramaddr, bp); /* virgin write */
done:
iodone(bp);
}
/*
* Start transfer between ram disk (ramaddr) and buffer. Actually completes
* synchronously of course, but what the heck.
*/
ramstart(ramaddr, bp)
memaddr ramaddr;
register struct buf *bp;
{
register u_int n, c;
memaddr bufaddr;
caddr_t seg6addr;
int error;
if (!(n = bp->b_bcount))
return;
#ifdef UCB_METER
if (ram_dkn >= 0)
dk_busy |= 1 << ram_dkn;
#endif
bufaddr = bftopaddr(bp); /* click address of buffer */
seg6addr = SEG6 + ((u_int)bp->b_un.b_addr & 077);
c = MIN(n, (SEG6+8192)-seg6addr);
for (;;) {
if (bp->b_flags & B_READ) {
mapseg5(ramaddr, ((btoc(8192)-1)<<8)|RO);
if (error = fmove(bufaddr, ((btoc(8192)-1)<<8)|RW,
SEG5, seg6addr, c))
break;
} else {
mapseg5(ramaddr, ((btoc(8192)-1)<<8)|RW);
if (error = fmove(bufaddr, ((btoc(8192)-1)<<8)|RO,
seg6addr, SEG5, c))
break;
}
if (!(n -= c))
break;
ramaddr += btoc(8192);
bufaddr += btoc(8192);
seg6addr = SEG6;
c = MIN(n, 8192);
}
normalseg5();
#ifdef UCB_METER
if (ram_dkn >= 0)
dk_busy &= ~(1 << ram_dkn);
#endif
if (error) {
bp->b_error = error;
bp->b_flags |= B_ERROR;
}
}
#endif NRAM