💾 Archived View for spam.works › mirrors › textfiles › computers › reagen.asc captured on 2023-12-28 at 17:21:07.

View Raw

More Information

⬅️ Previous capture (2023-06-14)

-=-=-=-=-=-=-

_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? 2(a)? Entr? fo? th? drive? i? th? /etc/conf/sdevice.? ?
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? 2(d)? Th? tw? nodes? fo? characte? an? bloc? device? ?
respectively.]

     rd   rdsk/rd0    c   0                    
     rd   dsk/rd0     b   0                    

[Exampl? 2(e)? Th? modifie? S01MOUNTFSY? file.]

     cd /                                         
     # Make a filesystem on the RAM disk.         
     /etc/mkfs /dev/dsk/rd0 2048:150              
     /etc/mountall /etc/fstab