textfiles/computers/reagen.asc

305 lines
7.8 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

_RAM DISK DRIVER FOR UNIX_
by Jeff Reagen
[LISTING ONE]
/* The following is a RAM disk driver developed for Unix Sys V/386
* release 3.2. -- Author: Jeff Reagen 05-02-90.
*/
#include "sys/types.h"
#include "sys/param.h"
#include "sys/immu.h"
#include "sys/fs/s5dir.h"
#include "sys/signal.h"
#include "sys/user.h"
#include "sys/errno.h"
#include "sys/cmn_err.h"
#include "sys/buf.h"
#define RD_SIZE_IN_PAGES 0x100L /* 256 4K pages => 1 MB */
#define RD_MAX 1 /* Max RAM Disks */
#define RAMDISK(x) (int)(x&0x0F) /* Ram disk number from dev */
#define DONT_SLEEP 1 /* sptalloc parameter */
/* For ioctl routines.
*/
#define RD_GETSIZE 1 /* return size of RAM disk */
struct rd_getsize { /* Structure passed to rdioctl */
daddr_t sectors;
long in_bytes;
};
/* Valid states for the RAM disk driver.
*/
#define RD_UNDEFINED 0x0000 /* Disk has not been setup */
#define RD_CONFIGURED 0x0001 /* Configured disk */
#define RD_OPEN 0x0002 /* Indicates disk has been opened */
/* The RAM disk is created iff the size field has been defined. Since
* sptalloc only allocates pages, make sure the size is
* some multiple of page size (4096).
*/
struct ram_config {
int state; /* current state */
caddr_t virt; /* virtual address of RAM disk */
long size; /* RAM disk size in units of 4K */
};
struct ram_config rd_cfg = {RD_UNDEFINED, (caddr_t)0, RD_SIZE_IN_PAGES};
extern caddr_t sptalloc();
/* rdinit - initialize the RAM disk.
*/
rdinit (dev)
dev_t dev;
{
/* Has a RAM disk been defined? */
if (rd_cfg.size == 0)
{
/* Just return silently - ram disk is not configured. */
return 0;
}
/* Last parameter 1 in sptalloc calls prevents sleep if no memory. */
if ((rd_cfg.virt = sptalloc (rd_cfg.size, PG_P,0,DONT_SLEEP)) == NULL)
{
cmn_err (CE_WARN,"Could not allocate enough memory for RAM disk.\n");
return 0;
}
rd_cfg.state |= RD_CONFIGURED;
return;
}
/* rdopen
*/
rdopen (dev)
dev_t dev;
{
int rdisk;
rdisk = RAMDISK(dev);
if ( rdisk >= RD_MAX)
{
/* RAM disk specified foes not exist. */
u.u_error = ENODEV;
return;
}
/* Make sure ram disk has been configured. */
if ( (rd_cfg.state & RD_CONFIGURED) != RD_CONFIGURED)
{
/* disk has not been configured! */
u.u_error = ENOMEM;
return;
}
/* RAM disk successfully opened. */
rd_cfg.state |= RD_OPEN;
}
/* rdclose - close the RAM disk.
*/
rdclose (dev)
dev_t dev;
{
rd_cfg.state &= ~RD_OPEN;
return;
}
/* rdstrategy - the entire synchronous transfer operation happens here.
*/
rdstrategy (bp)
register struct buf *bp;
{
register long req_start; /* start of transfer */
register long byte_size; /* Max capacity of RAM disk in bytes. */
int disk; /* RAM disk being requested for service. */
disk = RAMDISK(bp->b_dev);
/* Validate disk number. */
if (disk >= RD_MAX)
{
/* Disk does not exist. */
bp->b_flags |= B_ERROR;
bp->b_error = ENODEV;
iodone(bp);
return;
}
/* Validate request range. Reads can be trimmed back... */
byte_size = rd_cfg.size * NBPP;
req_start = bp->b_blkno * NBPSCTR;
bp->b_resid = 0; /* Number of bytes remaining after transfer */
/* Check for requests exceeding the upper bound of the disk. */
if (req_start + bp->b_bcount > byte_size)
{
if (bp->b_flags & B_READ)
{
/* Read */
/* Adjust residual count. */
bp->b_resid = req_start + bp->b_bcount - byte_size;
bp->b_bcount = byte_size - req_start;
}
else
{
/* Write - always fails */
bp->b_resid = bp->b_bcount;
bp->b_flags |= B_ERROR;
iodone (bp);
return;
}
}
/* Service the request. */
if (bp->b_flags & B_READ)
{
bcopy (rd_cfg.virt + req_start, bp->b_un.b_addr, bp->b_bcount);
}
else
{
bcopy (bp->b_un.b_addr, rd_cfg.virt + req_start, bp->b_bcount);
}
bp->b_flags &= ~B_ERROR; /* Make sure an error is NOT reported. */
iodone(bp);
return;
}
/* rdread - character read interface.
*/
rdread (dev)
dev_t dev;
{
/* Validate request based on number of 512 bytes sectors supported. */
if (physck ((daddr_t)rd_cfg.size << DPPSHFT, B_READ))
{
/* Have physio allocate the buffer header, then call rdstrategy. */
physio (rdstrategy, (struct buf *)NULL, dev, B_READ);
}
}
/* rdwrite - character write interface.
*/
rdwrite (dev)
dev_t dev;
{
/* Validate request based on number of 512 bytes sectors supported. */
if (physck ((daddr_t)rd_cfg.size << DPPSHFT, B_WRITE))
{
/* Have physio allocate the buffer header, then call rdstrategy. */
physio (rdstrategy, (struct buf *)NULL, dev, B_WRITE);
}
}
/* rdioctl - returns size of RAM disk.
*/
rdioctl (dev, command, arg, mode)
dev_t dev;
int command;
int *arg;
int mode;
{
struct rd_getsize sizes;
if ( RAMDISK(dev) > RD_MAX || !(rd_cfg.state&RD_CONFIGURED) )
{
u.u_error = ENODEV;
return;
}
switch (command) {
case RD_GETSIZE:
sizes.sectors = rd_cfg.size << DPPSHFT;
sizes.in_bytes = rd_cfg.size * NBPP;
/* Now transfer the request to user space */
if (copyout (&sizes, arg, sizeof (sizes)) )
{
u.u_error = EFAULT;
}
break;
default:
/* Error - do not recognize command submitted. */
u.u_error = EINVAL;
return;
}
}
/* rdintr - the RAM disk does not generate hardware interrupts,
* so this routine simply prints a warning message and returns.
*/
rdintr ()
{
cmn_err (CE_WARN, "RAM disk took a spurious hardware interrupt.\n");
}
/* rdprint - send messages concerning the RAM disk to the console.
*/
rdprint (dev, str)
dev_t dev;
char *str;
{
cmn_err (CE_NOTE, "%s on Ram Disk %d.\n", str, RAMDISK (dev));
}
[Example 1: How an application queries the RAM disk's size]
#include "sys/types.h"
main ()
{
int fd;
struct rd_size {
daddr_t sector_count;
long b_count;
} ram_disk_size;
if ( (fd = open ("/dev/rdsk/rd0", O_RDONLY)) < 0)
{
printf ("Could not open RAM disk to do ioctl.\n");
exit (1);
}
if ( ioctl (fd, RD_GETSIZE, &ram_disk_size) < 0)
{
printf ("Could not determine size of RAM disk.\n");
exit (2);
}
printf ("The RAM disk consists of %d sectors occupying %d bytes.\n",
ram_disk_size.sector_count, ram_disk_size.b_count);
}
[Exampl<70> 2(a)<29> Entr<74> fo<66> th<74> drive<76> i<> th<74> /etc/conf/sdevice.<2E> <20>
file.]
rd Y 1 0 0 0 0 0 0 0
[Example 2(b): Entry in the master device file.]
rd ocrwiI icbo rd 0 0 1 2 -1
[Example 2(c): The idinstall command.]
/etc/conf/bin/idinstall -a -m -k rd
[Exampl<70> 2(d)<29> Th<54> tw<74> nodes<65> fo<66> characte<74> an<61> bloc<6F> device<63> <20>
respectively.]
rd rdsk/rd0 c 0
rd dsk/rd0 b 0
[Exampl<70> 2(e)<29> Th<54> modifie<69> S01MOUNTFSY<53> file.]
cd /
# Make a filesystem on the RAM disk.
/etc/mkfs /dev/dsk/rd0 2048:150
/etc/mountall /etc/fstab