home *** CD-ROM | disk | FTP | other *** search
/ PC-Online 1996 May / PCOnline_05_1996.bin / linux / source / kernel-s / v1.1 / ramdisk / ramdisk.c
C/C++ Source or Header  |  1995-10-10  |  5KB  |  188 lines

  1. /*
  2.  *  linux/kernel/blk_drv/ramdisk.c
  3.  *
  4.  *  Written by Theodore Ts'o, 12/2/91
  5.  *
  6.  * Modifications by Fred N. van Kempen to allow for bootable root
  7.  * disks (which are used in LINUX/Pro).  Also some cleanups.  03/03/93
  8.  */
  9.  
  10.  
  11. #include <linux/config.h>
  12. #include <linux/sched.h>
  13. #include <linux/minix_fs.h>
  14. #include <linux/fs.h>
  15. #include <linux/kernel.h>
  16. #include <linux/string.h>
  17. #include <asm/system.h>
  18. #include <asm/segment.h>
  19.  
  20. #define MAJOR_NR  MEM_MAJOR
  21. #include "blk.h"
  22.  
  23. #define RAMDISK_MINOR    1
  24.  
  25.  
  26. char    *rd_start;
  27. int    rd_length = 0;
  28. static int rd_blocksizes[2] = {0, 0};
  29.  
  30. extern void wait_for_keypress(void);
  31.  
  32. static void do_rd_request(void)
  33. {
  34.     int    len;
  35.     char    *addr;
  36.  
  37. repeat:
  38.     INIT_REQUEST;
  39.     addr = rd_start + (CURRENT->sector << 9);
  40.     len = CURRENT->current_nr_sectors << 9;
  41.  
  42.     if ((MINOR(CURRENT->dev) != RAMDISK_MINOR) ||
  43.         (addr+len > rd_start+rd_length)) {
  44.         end_request(0);
  45.         goto repeat;
  46.     }
  47.     if (CURRENT-> cmd == WRITE) {
  48.         (void ) memcpy(addr,
  49.                   CURRENT->buffer,
  50.                   len);
  51.     } else if (CURRENT->cmd == READ) {
  52.         (void) memcpy(CURRENT->buffer, 
  53.                   addr,
  54.                   len);
  55.     } else
  56.         panic("RAMDISK: unknown RAM disk command !\n");
  57.     end_request(1);
  58.     goto repeat;
  59. }
  60.  
  61. static struct file_operations rd_fops = {
  62.     NULL,            /* lseek - default */
  63.     block_read,        /* read - general block-dev read */
  64.     block_write,        /* write - general block-dev write */
  65.     NULL,            /* readdir - bad */
  66.     NULL,            /* select */
  67.     NULL,            /* ioctl */
  68.     NULL,            /* mmap */
  69.     NULL,            /* no special open code */
  70.     NULL,            /* no special release code */
  71.     block_fsync        /* fsync */
  72. };
  73.  
  74. /*
  75.  * Returns amount of memory which needs to be reserved.
  76.  */
  77. long rd_init(long mem_start, int length)
  78. {
  79.     int    i;
  80.     char    *cp;
  81.  
  82.     if (register_blkdev(MEM_MAJOR,"rd",&rd_fops)) {
  83.         printk("RAMDISK: Unable to get major %d.\n", MEM_MAJOR);
  84.         return 0;
  85.     }
  86.     blk_dev[MEM_MAJOR].request_fn = DEVICE_REQUEST;
  87.     rd_start = (char *) mem_start;
  88.     rd_length = length;
  89.     cp = rd_start;
  90.     for (i=0; i < length; i++)
  91.         *cp++ = '\0';
  92.  
  93.     for(i=0;i<2;i++) rd_blocksizes[i] = 1024;
  94.     blksize_size[MAJOR_NR] = rd_blocksizes;
  95.  
  96.     return(length);
  97. }
  98.  
  99. /*
  100.  * If the root device is the RAM disk, try to load it.
  101.  * In order to do this, the root device is originally set to the
  102.  * floppy, and we later change it to be RAM disk.
  103.  */
  104. void rd_load(void)
  105. {
  106.     struct buffer_head *bh;
  107.     struct minix_super_block s;
  108.     int        block, tries;
  109.     int        i = 1;
  110.     int        nblocks;
  111.     char        *cp;
  112.  
  113.     /* If no RAM disk specified, give up early. */
  114.     if (!rd_length) return;
  115.         /* Pat's ugly hack */
  116.         printk("\n\nPlease remove the boot kernel disk from your floppy drive, insert a\n");
  117.         printk("root/install disk (such as one of the Slackware color144, colrlite,\n");
  118.         printk("tty144, or tty12 disks) or some other disk you wish to load into a\n");
  119.         printk("ramdisk and boot, and then press ENTER to continue.\n\n");
  120.         wait_for_keypress();
  121.  
  122.     printk("RAMDISK: %d bytes, starting at 0x%x\n",
  123.                     rd_length, (int) rd_start);
  124.  
  125.     /* If we are doing a diskette boot, we might have to pre-load it. */
  126.     if (MAJOR(ROOT_DEV) != FLOPPY_MAJOR) return;
  127.  
  128.     /*
  129.      * Check for a super block on the diskette.
  130.      * The old-style boot/root diskettes had their RAM image
  131.      * starting at block 512 of the boot diskette.  LINUX/Pro
  132.      * uses the enire diskette as a file system, so in that
  133.      * case, we have to look at block 0.  Be intelligent about
  134.      * this, and check both... - FvK
  135.      */
  136.     for (tries = 0; tries < 1000; tries += 512) {
  137.         block = tries;
  138.         bh = breada(ROOT_DEV,block+1,BLOCK_SIZE, 0,  PAGE_SIZE);
  139.         if (!bh) {
  140.             printk("RAMDISK: I/O error while looking for super block!\n");
  141.             return;
  142.         }
  143.  
  144.         /* This is silly- why do we require it to be a MINIX FS? */
  145.         *((struct minix_super_block *) &s) =
  146.             *((struct minix_super_block *) bh->b_data);
  147.         brelse(bh);
  148.         nblocks = s.s_nzones << s.s_log_zone_size;
  149.         if (s.s_magic != MINIX_SUPER_MAGIC &&
  150.             s.s_magic != MINIX_SUPER_MAGIC2) {
  151.             printk("RAMDISK: trying old-style RAM image.\n");
  152.             continue;
  153.         }
  154.  
  155.         if (nblocks > (rd_length >> BLOCK_SIZE_BITS)) {
  156.             printk("RAMDISK: image too big! (%d/%d blocks)\n",
  157.                     nblocks, rd_length >> BLOCK_SIZE_BITS);
  158.             return;
  159.         }
  160.         printk("RAMDISK: Loading %d blocks into RAM disk", nblocks);
  161.  
  162.         /* We found an image file system.  Load it into core! */
  163.         cp = rd_start;
  164.         while (nblocks) {
  165.             if (nblocks > 2) 
  166.                     bh = breada(ROOT_DEV, block, BLOCK_SIZE, 0,  PAGE_SIZE);
  167.             else
  168.                 bh = bread(ROOT_DEV, block, BLOCK_SIZE);
  169.             if (!bh) {
  170.                 printk("RAMDISK: I/O error on block %d, aborting!\n", 
  171.                 block);
  172.                 return;
  173.             }
  174.             (void) memcpy(cp, bh->b_data, BLOCK_SIZE);
  175.             brelse(bh);
  176.             if (!(nblocks-- & 15)) printk(".");
  177.             cp += BLOCK_SIZE;
  178.             block++;
  179.             i++;
  180.         }
  181.         printk("\ndone\n");
  182.  
  183.         /* We loaded the file system image.  Prepare for mounting it. */
  184.         ROOT_DEV = ((MEM_MAJOR << 8) | RAMDISK_MINOR);
  185.         return;
  186.     }
  187. }
  188.