GENWiki

Premier IT Outsourcing and Support Services within the UK

User Tools

Site Tools


archive:computers:reagen

_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©: 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                     



/home/gen.uk/domains/wiki.gen.uk/public_html/data/pages/archive/computers/reagen.txt · Last modified: 2001/11/08 10:19 by 127.0.0.1

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki