Goto sanos source index

//
// ramdisk.c
//
// RAM disk driver
//
// Copyright (C) 2002 Michael Ringgaard. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// 
// 1. Redistributions of source code must retain the above copyright 
//    notice, this list of conditions and the following disclaimer.  
// 2. Redistributions in binary form must reproduce the above copyright
//    notice, this list of conditions and the following disclaimer in the
//    documentation and/or other materials provided with the distribution.  
// 3. Neither the name of the project nor the names of its contributors
//    may be used to endorse or promote products derived from this software
//    without specific prior written permission. 
// 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
// SUCH DAMAGE.
// 

#include <os/krnl.h>

struct ramdisk {
  unsigned int blks;
  char *data;
};

static int ramdisk_ioctl(struct dev *dev, int cmd, void *args, size_t size) {
  struct ramdisk *rd = (struct ramdisk *) dev->privdata;

  switch (cmd) {
    case IOCTL_GETDEVSIZE:
      return rd->blks;

    case IOCTL_GETBLKSIZE:
      return SECTORSIZE;
  }

  return -ENOSYS;
}

static int ramdisk_read(struct dev *dev, void *buffer, size_t count, blkno_t blkno, int flags) {
  struct ramdisk *rd = (struct ramdisk *) dev->privdata;

  if (count == 0) return 0;
  if (blkno + count / SECTORSIZE > rd->blks) {
    count = (rd->blks - blkno) * SECTORSIZE;
  }
  memcpy(buffer, rd->data + blkno * SECTORSIZE, count);
  return count;
}

static int ramdisk_write(struct dev *dev, void *buffer, size_t count, blkno_t blkno, int flags) {
  struct ramdisk *rd = (struct ramdisk *) dev->privdata;

  if (count == 0) return 0;
  if (blkno + count / SECTORSIZE > rd->blks) return -EFAULT;
  memcpy(rd->data + blkno * SECTORSIZE, buffer, count);
  return count;
}

struct driver ramdisk_driver = {
  "ramdisk",
  DEV_TYPE_BLOCK,
  ramdisk_ioctl,
  ramdisk_read,
  ramdisk_write
};

int __declspec(dllexport) ramdisk(struct unit *unit, char *opts) {
  struct ramdisk *rd;
  char devname[DEVNAMELEN];
  int size;
  dev_t devno;
  char *data;

  get_option(opts, "devname", devname, DEVNAMELEN, "rd#");
  size = get_num_option(opts, "size", 1440) * 1024;

  data = kmalloc(size);
  if (!data) return -ENOMEM;

  rd = kmalloc(sizeof(struct ramdisk));
  if (!rd) return -ENOMEM;

  rd->blks = size / SECTORSIZE;
  rd->data = data;

  devno = dev_make(devname, &ramdisk_driver, NULL, rd);
  
  kprintf(KERN_INFO "%s: ramdisk (%d KB)\n", device(devno)->name, size / 1024);
  return 0;
}

int create_initrd() {
  struct ramdisk *rd;
  dev_t devno;
  int size;

  size = syspage->ldrparams.initrd_size;
  if (size == 0) return 0;

  rd = kmalloc(sizeof(struct ramdisk));
  if (!rd) return -ENOMEM;

  rd->blks = size / SECTORSIZE;
  rd->data = (char *) INITRD_ADDRESS;

  devno = dev_make("initrd", &ramdisk_driver, NULL, rd);
  
  kprintf(KERN_INFO "%s: ramdisk (%d KB)\n", device(devno)->name, size / 1024);
  return 0;
}