diff options
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/ramdisk.c | 633 | ||||
-rw-r--r-- | sys/dev/ramdisk.h | 91 |
2 files changed, 0 insertions, 724 deletions
diff --git a/sys/dev/ramdisk.c b/sys/dev/ramdisk.c deleted file mode 100644 index fd244b7a35f..00000000000 --- a/sys/dev/ramdisk.c +++ /dev/null @@ -1,633 +0,0 @@ -/* $OpenBSD: ramdisk.c,v 1.53 2011/06/05 18:40:33 matthew Exp $ */ -/* $NetBSD: ramdisk.c,v 1.8 1996/04/12 08:30:09 leo Exp $ */ - -/* - * Copyright (c) 1995 Gordon W. Ross, Leo Weppelman. - * 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. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * 4. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by - * Gordon W. Ross and Leo Weppelman. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. - */ - -/* - * This implements a general-purpose RAM-disk. - * See ramdisk.h for notes on the config types. - * - * Note that this driver provides the same functionality - * as the MFS filesystem hack, but this is better because - * you can use this for any filesystem type you'd like! - * - * Credit for most of the kmem ramdisk code goes to: - * Leo Weppelman (atari) and Phil Nelson (pc532) - * Credit for the ideas behind the "user space RAM" code goes - * to the authors of the MFS implementation. - */ - -#include <sys/param.h> -#include <sys/kernel.h> -#include <sys/malloc.h> -#include <sys/systm.h> -#include <sys/buf.h> -#include <sys/device.h> -#include <sys/file.h> -#include <sys/disk.h> -#include <sys/proc.h> -#include <sys/conf.h> -#include <sys/disklabel.h> -#include <sys/dkio.h> - -#include <uvm/uvm_extern.h> - -#include <dev/ramdisk.h> - -/* - * By default, include the user-space functionality. - * Use: option RAMDISK_SERVER=0 to turn it off. - */ -#if !defined(RAMDISK_SERVER) && !defined(SMALL_KERNEL) -#define RAMDISK_SERVER 1 -#endif - -/* - * XXX: the "control" unit is (base unit + 16). - * We should just use the cdev as the "control", but - * that interferes with the security stuff preventing - * simultaneous use of raw and block devices. - * - * XXX Assumption: 16 RAM-disks are enough! - */ -#define RD_MAX_UNITS 0x10 -#define RD_IS_CTRL(dev) (DISKPART(dev) == RAW_PART) - -/* autoconfig stuff... */ - -struct rd_softc { - struct device sc_dev; /* REQUIRED first entry */ - struct disk sc_dk; /* hook for generic disk handling */ - struct rd_conf sc_rd; -#if RAMDISK_SERVER - struct buf *sc_buflist; -#endif -}; -/* shorthand for fields in sc_rd: */ -#define sc_addr sc_rd.rd_addr -#define sc_size sc_rd.rd_size -#define sc_type sc_rd.rd_type - -void rdattach(int); -void rd_attach(struct device *, struct device *, void *); -void rdgetdisklabel(dev_t, struct rd_softc *, struct disklabel *, int); - -/* - * Some ports (like i386) use a swapgeneric that wants to - * snoop around in this rd_cd structure. It is preserved - * (for now) to remain compatible with such practice. - * XXX - that practice is questionable... - */ -struct cfdriver rd_cd = { - NULL, "rd", DV_DISK -}; - -/* - * Here we define a cfattach structure for inserting any new rd device into the - * device tree. This is needed by some archs that look for bootable devices in - * there. - */ -int rd_probe(struct device *, void *, void *); -int rd_detach(struct device *, int); - -struct cfattach rd_ca = { - sizeof(struct rd_softc), rd_probe, rd_attach, - rd_detach -}; - -void rdstrategy(struct buf *bp); - -int ramdisk_ndevs; -void *ramdisk_devs[RD_MAX_UNITS]; - -/* - * This is called if we are configured as a pseudo-device - */ -void -rdattach(int n) -{ - struct rd_softc *sc; - struct cfdata *cf; - int i; - -#ifdef DIAGNOSTIC - if (ramdisk_ndevs) { - printf("ramdisk: multiple attach calls?\n"); - return; - } -#endif - - /* XXX: Are we supposed to provide a default? */ - if (n < 1) - n = 1; - if (n > RD_MAX_UNITS) - n = RD_MAX_UNITS; - ramdisk_ndevs = n; - - /* XXX: Fake-up rd_cd (see above) */ - rd_cd.cd_ndevs = ramdisk_ndevs; - rd_cd.cd_devs = ramdisk_devs; - - /* Attach as if by autoconfig. */ - cf = malloc(sizeof(struct cfdata), M_DEVBUF, M_NOWAIT | M_ZERO); - if (cf == NULL) { - printf("WARNING: no memory for cfdata struct\n"); - return; - } - cf->cf_attach = &rd_ca; - cf->cf_driver = &rd_cd; - - for (i = 0; i < n; i++) { - sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO); - if (snprintf(sc->sc_dev.dv_xname, sizeof(sc->sc_dev.dv_xname), - "rd%d", i) >= sizeof(sc->sc_dev.dv_xname)) { - printf("rdattach: device name too long\n"); - free(sc, M_DEVBUF); - return; - } - ramdisk_devs[i] = sc; - sc->sc_dev.dv_unit = i; - sc->sc_dev.dv_class = DV_DISK; - sc->sc_dev.dv_parent = NULL; - sc->sc_dev.dv_cfdata = cf; - TAILQ_INSERT_TAIL(&alldevs, &sc->sc_dev, dv_list); - device_ref(&sc->sc_dev); - rd_attach(NULL, &sc->sc_dev, NULL); - } -} - -void -rd_attach(struct device *parent, struct device *self, void *aux) -{ - struct rd_softc *sc = (struct rd_softc *)self; - - /* XXX - Could accept aux info here to set the config. */ -#ifdef RAMDISK_HOOKS - /* - * This external function might setup a pre-loaded disk. - * All it would need to do is setup the rd_conf struct. - * See sys/arch/sun3/dev/rd_root.c for an example. - */ - rd_attach_hook(sc->sc_dev.dv_unit, &sc->sc_rd); -#endif - - /* - * Initialize and attach the disk structure. - */ - sc->sc_dk.dk_name = sc->sc_dev.dv_xname; - disk_attach(&sc->sc_dev, &sc->sc_dk); -} - -/* - * operational routines: - * open, close, read, write, strategy, - * ioctl, dump, size - */ - -#if RAMDISK_SERVER -int rd_server_loop(struct rd_softc *sc); -int rd_ioctl_server(struct rd_softc *sc, - struct rd_conf *urd, struct proc *proc); -#endif -int rd_ioctl_kalloc(struct rd_softc *sc, - struct rd_conf *urd, struct proc *proc); - -dev_type_open(rdopen); -dev_type_close(rdclose); -dev_type_read(rdread); -dev_type_write(rdwrite); -dev_type_ioctl(rdioctl); -dev_type_size(rdsize); -dev_type_dump(rddump); - -int -rddump(dev_t dev, daddr64_t blkno, caddr_t va, size_t size) -{ - return (ENODEV); -} - -daddr64_t -rdsize(dev_t dev) -{ - int part, unit; - struct rd_softc *sc; - - /* Disallow control units. */ - unit = DISKUNIT(dev); - if (unit >= ramdisk_ndevs) - return (0); - sc = ramdisk_devs[unit]; - if (sc == NULL) - return (0); - - if (sc->sc_type == RD_UNCONFIGURED) - return (0); - - rdgetdisklabel(dev, sc, sc->sc_dk.dk_label, 0); - part = DISKPART(dev); - if (part >= sc->sc_dk.dk_label->d_npartitions) - return (0); - return (DL_GETPSIZE(&sc->sc_dk.dk_label->d_partitions[part]) * - (sc->sc_dk.dk_label->d_secsize / DEV_BSIZE)); -} - -int -rdopen(dev_t dev, int flag, int fmt, struct proc *proc) -{ - int unit; - struct rd_softc *sc; - - unit = DISKUNIT(dev); - if (unit >= ramdisk_ndevs) - return (ENXIO); - sc = ramdisk_devs[unit]; - if (sc == NULL) - return (ENXIO); - - /* - * The control device is not exclusive, and can - * open uninitialized units (so you can setconf). - */ - if (RD_IS_CTRL(dev)) - return (0); - -#ifdef RAMDISK_HOOKS - /* Call the open hook to allow loading the device. */ - rd_open_hook(unit, &sc->sc_rd); -#endif - - /* - * This is a normal, "slave" device, so - * enforce initialized, exclusive open. - */ - if (sc->sc_type == RD_UNCONFIGURED) - return (ENXIO); - - /* - * Make sure we have read the disklabel. - */ - rdgetdisklabel(dev, sc, sc->sc_dk.dk_label, 0); - return (0); -} - -int -rdclose(dev_t dev, int flag, int fmt, struct proc *proc) -{ - return (0); -} - -int -rdread(dev_t dev, struct uio *uio, int flags) -{ - return (physio(rdstrategy, dev, B_READ, minphys, uio)); -} - -int -rdwrite(dev_t dev, struct uio *uio, int flags) -{ - return (physio(rdstrategy, dev, B_WRITE, minphys, uio)); -} - -/* - * Handle I/O requests, either directly, or - * by passing them to the server process. - */ -void -rdstrategy(struct buf *bp) -{ - int unit, s; - struct rd_softc *sc; - caddr_t addr; - size_t off, xfer; - - unit = DISKUNIT(bp->b_dev); - sc = ramdisk_devs[unit]; - - /* Sort rogue requests out */ - if (sc == NULL || bp->b_blkno < 0 || - (bp->b_bcount % sc->sc_dk.dk_label->d_secsize) != 0) { - bp->b_error = EINVAL; - goto bad; - } - - /* Do not write on "no trespassing" areas... */ - if (bounds_check_with_label(bp, sc->sc_dk.dk_label) <= 0) - goto bad; - - switch (sc->sc_type) { -#if RAMDISK_SERVER - case RD_UMEM_SERVER: - /* Just add this job to the server's queue. */ - bp->b_actf = sc->sc_buflist; - sc->sc_buflist = bp; - if (bp->b_actf == NULL) { - /* server queue was empty. */ - wakeup((caddr_t)sc); - /* see rd_server_loop() */ - } - /* no biodone in this case */ - return; -#endif /* RAMDISK_SERVER */ - - case RD_KMEM_FIXED: - case RD_KMEM_ALLOCATED: - /* These are in kernel space. Access directly. */ - bp->b_resid = bp->b_bcount; - off = (bp->b_blkno << DEV_BSHIFT); - xfer = bp->b_bcount; - if (xfer > (sc->sc_size - off)) - xfer = (sc->sc_size - off); - addr = sc->sc_addr + off; - if (bp->b_flags & B_READ) - bcopy(addr, bp->b_data, xfer); - else - bcopy(bp->b_data, addr, xfer); - bp->b_resid -= xfer; - break; - - default: - bp->b_error = EIO; -bad: - bp->b_flags |= B_ERROR; - bp->b_resid = bp->b_bcount; - break; - } - - s = splbio(); - biodone(bp); - splx(s); -} - -int -rdioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *proc) -{ - struct disklabel *lp; - struct rd_softc *sc; - struct rd_conf *urd; - int unit = DISKUNIT(dev), error; - - sc = ramdisk_devs[unit]; - - urd = (struct rd_conf *)data; - switch (cmd) { - case DIOCRLDINFO: - if (sc->sc_type == RD_UNCONFIGURED) - break; - lp = malloc(sizeof(*lp), M_TEMP, M_WAITOK); - rdgetdisklabel(dev, sc, lp, 0); - bcopy(lp, sc->sc_dk.dk_label, sizeof(*lp)); - free(lp, M_TEMP); - return (0); - - case DIOCGPDINFO: - if (sc->sc_type == RD_UNCONFIGURED) - break; - rdgetdisklabel(dev, sc, (struct disklabel *)data, 1); - return (0); - - case DIOCGDINFO: - if (sc->sc_type == RD_UNCONFIGURED) - break; - *(struct disklabel *)data = *(sc->sc_dk.dk_label); - return (0); - - case DIOCGPART: - ((struct partinfo *)data)->disklab = sc->sc_dk.dk_label; - ((struct partinfo *)data)->part = - &sc->sc_dk.dk_label->d_partitions[DISKPART(dev)]; - return (0); - - case DIOCWDINFO: - case DIOCSDINFO: - if (sc->sc_type == RD_UNCONFIGURED) - break; - if ((flag & FWRITE) == 0) - return (EBADF); - - error = setdisklabel(sc->sc_dk.dk_label, - (struct disklabel *)data, sc->sc_dk.dk_openmask); - if (error == 0) { - if (cmd == DIOCWDINFO) - error = writedisklabel(DISKLABELDEV(dev), - rdstrategy, sc->sc_dk.dk_label); - } - return (error); - - case RD_GETCONF: - /* If this is not the control device, punt! */ - if (RD_IS_CTRL(dev) == 0) - break; - *urd = sc->sc_rd; - return (0); - - case RD_SETCONF: - /* If this is not the control device, punt! */ - if (RD_IS_CTRL(dev) == 0) - break; - /* Can only set it once. */ - if (sc->sc_type != RD_UNCONFIGURED) - break; - switch (urd->rd_type) { - case RD_KMEM_ALLOCATED: - return (rd_ioctl_kalloc(sc, urd, proc)); -#if RAMDISK_SERVER - case RD_UMEM_SERVER: - return (rd_ioctl_server(sc, urd, proc)); -#endif - default: - break; - } - break; - - default: - return (ENOTTY); - } - return (EINVAL); -} - -void -rdgetdisklabel(dev_t dev, struct rd_softc *sc, struct disklabel *lp, - int spoofonly) -{ - bzero(lp, sizeof(struct disklabel)); - - lp->d_secsize = DEV_BSIZE; - lp->d_ntracks = 1; - lp->d_nsectors = sc->sc_size >> DEV_BSHIFT; - lp->d_ncylinders = 1; - lp->d_secpercyl = lp->d_nsectors; - if (lp->d_secpercyl == 0) { - lp->d_secpercyl = 100; - /* as long as it's not 0 - readdisklabel divides by it (?) */ - } - - strncpy(lp->d_typename, "RAM disk", sizeof(lp->d_typename)); - lp->d_type = DTYPE_SCSI; - strncpy(lp->d_packname, "fictitious", sizeof(lp->d_packname)); - DL_SETDSIZE(lp, lp->d_nsectors); - lp->d_version = 1; - - lp->d_magic = DISKMAGIC; - lp->d_magic2 = DISKMAGIC; - lp->d_checksum = dkcksum(lp); - - /* - * Call the generic disklabel extraction routine - */ - readdisklabel(DISKLABELDEV(dev), rdstrategy, lp, spoofonly); -} - -/* - * Handle ioctl RD_SETCONF for (sc_type == RD_KMEM_ALLOCATED) - * Just allocate some kernel memory and return. - */ -int -rd_ioctl_kalloc(struct rd_softc *sc, struct rd_conf *urd, struct proc *proc) -{ - vaddr_t addr; - vsize_t size; - - /* Sanity check the size. */ - size = urd->rd_size; - addr = uvm_km_zalloc(kernel_map, size); - if (!addr) - return (ENOMEM); - - /* This unit is now configured. */ - sc->sc_addr = (caddr_t)addr; /* kernel space */ - sc->sc_size = (size_t)size; - sc->sc_type = RD_KMEM_ALLOCATED; - return (0); -} - -int -rd_probe(struct device *parent, void *match_, void *aux) -{ - return (0); -} - -int -rd_detach(struct device *self, int flags) -{ - return (0); -} - -#if RAMDISK_SERVER - -/* - * Handle ioctl RD_SETCONF for (sc_type == RD_UMEM_SERVER) - * Set config, then become the I/O server for this unit. - */ -int -rd_ioctl_server(struct rd_softc *sc, struct rd_conf *urd, struct proc *proc) -{ - vaddr_t end; - int error; - - /* Sanity check addr, size. */ - end = (vaddr_t) (urd->rd_addr + urd->rd_size); - - if ((end >= VM_MAXUSER_ADDRESS) || (end < ((vaddr_t) urd->rd_addr)) ) - return (EINVAL); - - /* This unit is now configured. */ - sc->sc_addr = urd->rd_addr; /* user space */ - sc->sc_size = urd->rd_size; - sc->sc_type = RD_UMEM_SERVER; - - /* Become the server daemon */ - error = rd_server_loop(sc); - - /* This server is now going away! */ - sc->sc_type = RD_UNCONFIGURED; - sc->sc_addr = 0; - sc->sc_size = 0; - return (error); -} - -int rd_sleep_pri = PWAIT | PCATCH; - -int -rd_server_loop(struct rd_softc *sc) -{ - struct buf *bp; - caddr_t addr; /* user space address */ - size_t off; /* offset into "device" */ - size_t xfer; /* amount to transfer */ - int error, s; - - for (;;) { - /* Wait for some work to arrive. */ - while (sc->sc_buflist == NULL) { - error = tsleep((caddr_t)sc, rd_sleep_pri, "rd_idle", 0); - if (error) - return (error); - } - - /* Unlink buf from head of list. */ - bp = sc->sc_buflist; - sc->sc_buflist = bp->b_actf; - bp->b_actf = NULL; - - /* Do the transfer to/from user space. */ - error = 0; - bp->b_resid = bp->b_bcount; - off = (bp->b_blkno << DEV_BSHIFT); - if (off >= sc->sc_size) { - if (bp->b_flags & B_READ) - goto done; /* EOF (not an error) */ - error = EIO; - goto done; - } - xfer = bp->b_resid; - if (xfer > (sc->sc_size - off)) - xfer = (sc->sc_size - off); - addr = sc->sc_addr + off; - if (bp->b_flags & B_READ) - error = copyin(addr, bp->b_data, xfer); - else - error = copyout(bp->b_data, addr, xfer); - if (!error) - bp->b_resid -= xfer; - - done: - if (error) { - bp->b_error = error; - bp->b_flags |= B_ERROR; - } - s = splbio(); - biodone(bp); - splx(s); - } -} - -#endif /* RAMDISK_SERVER */ diff --git a/sys/dev/ramdisk.h b/sys/dev/ramdisk.h deleted file mode 100644 index f2be89fa350..00000000000 --- a/sys/dev/ramdisk.h +++ /dev/null @@ -1,91 +0,0 @@ -/* $OpenBSD: ramdisk.h,v 1.5 2002/03/14 01:26:52 millert Exp $ */ -/* $NetBSD: ramdisk.h,v 1.4 1996/03/22 23:02:04 gwr Exp $ */ - -/* - * Copyright (c) 1995 Gordon W. Ross - * 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. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission. - * 4. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Gordon W. Ross - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. - */ - -/* - * RAM-disk ioctl functions: - */ - -#include <sys/ioccom.h> - -struct rd_conf { - caddr_t rd_addr; - size_t rd_size; - int rd_type; -}; - -#define RD_GETCONF _IOR('r', 0, struct rd_conf) /* get unit config */ -#define RD_SETCONF _IOW('r', 1, struct rd_conf) /* set unit config */ - -/* - * There are three configurations supported for each unit, - * reflected in the value of the rd_type field: - */ -#define RD_UNCONFIGURED 0 -/* - * Not yet configured. Open returns ENXIO. - */ -#define RD_KMEM_FIXED 1 -/* - * Disk image resident in kernel (patched in or loaded). - * Requires that the function: rd_set_kmem() is called to - * attach the (initialized) kernel memory to be used by the - * device. It can be initialized by an "open hook" if this - * driver is compiled with the RD_OPEN_HOOK option. - * No attempt will ever be made to free this memory. - */ -#define RD_KMEM_ALLOCATED 2 -/* - * Small, wired-down chunk of kernel memory obtained from - * kmem_alloc(). The allocation is performed by an ioctl - * call on the "control" unit (regular unit + 16) - */ -#define RD_UMEM_SERVER 3 -/* - * Indirect access to user-space of a user-level server. - * (Like the MFS hack, but better! 8^) Device operates - * only while the server has the control device open and - * continues to service I/O requests. The process that - * does this setconf will become the I/O server. This - * configuration type can be disabled using: - * option RAMDISK_SERVER=0 - */ - -#ifdef _KERNEL -/* - * If the option RAMDISK_HOOKS is on, then these functions are - * called by the ramdisk driver to allow machine-dependent to - * match/configure and/or load each ramdisk unit. - */ -extern void rd_attach_hook(int unit, struct rd_conf *); -extern void rd_open_hook(int unit, struct rd_conf *); -#endif |