summaryrefslogtreecommitdiff
path: root/sys/arch/atari/dev/ramd.c
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>1995-10-18 08:53:40 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>1995-10-18 08:53:40 +0000
commitd6583bb2a13f329cf0332ef2570eb8bb8fc0e39c (patch)
treeece253b876159b39c620e62b6c9b1174642e070e /sys/arch/atari/dev/ramd.c
initial import of NetBSD tree
Diffstat (limited to 'sys/arch/atari/dev/ramd.c')
-rw-r--r--sys/arch/atari/dev/ramd.c481
1 files changed, 481 insertions, 0 deletions
diff --git a/sys/arch/atari/dev/ramd.c b/sys/arch/atari/dev/ramd.c
new file mode 100644
index 00000000000..46f7fab41bf
--- /dev/null
+++ b/sys/arch/atari/dev/ramd.c
@@ -0,0 +1,481 @@
+/* $NetBSD: ramd.c,v 1.5 1995/08/12 20:31:02 mycroft Exp $ */
+
+/*
+ * Copyright (c) 1995 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Leo Weppelman.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * 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.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/buf.h>
+#include <sys/proc.h>
+#include <sys/device.h>
+#include <sys/ioctl.h>
+#include <sys/fcntl.h>
+#include <sys/conf.h>
+#include <sys/disklabel.h>
+#include <sys/disk.h>
+#include <sys/dkbad.h>
+
+/*
+ * Misc. defines:
+ */
+#define RAMD_CHUNK (9 * 512) /* Chunk-size for auto-load */
+#define RAMD_NDEV 2 /* Number of devices configured */
+
+struct ramd_info {
+ u_long ramd_size; /* Size of disk in bytes */
+ u_long ramd_flag; /* see defs below */
+ dev_t ramd_dev; /* device to load from */
+ u_long ramd_state; /* runtime state see defs below */
+ caddr_t ramd_addr; /* Kernel virtual addr */
+};
+
+/*
+ * ramd_flag:
+ */
+#define RAMD_LOAD 0x01 /* Auto load when first opened */
+#define RAMD_LCOMP 0x02 /* Input is compressed */
+
+/*
+ * ramd_state:
+ */
+#define RAMD_ALLOC 0x01 /* Memory is allocated */
+#define RAMD_OPEN 0x02 /* Ramdisk is open */
+#define RAMD_INOPEN 0x04 /* Ramdisk is being opened */
+#define RAMD_WANTED 0x08 /* Someone is waiting on struct */
+#define RAMD_LOADED 0x10 /* Ramdisk is properly loaded */
+
+struct ramd_info rd_info[RAMD_NDEV] = {
+ {
+ 1105920, /* 1Mb in 2160 sectors */
+ RAMD_LOAD, /* auto-load this device */
+ MAKEDISKDEV(2, 0, 1), /* XXX: This is crap! (720Kb flop) */
+ 0, /* Will be set at runtime */
+ NULL /* Will be set at runtime */
+ },
+ {
+ 1474560, /* 1.44Mb in 2880 sectors */
+ RAMD_LOAD, /* auto-load this device */
+ MAKEDISKDEV(2, 0, 1), /* XXX: This is crap! (720Kb flop) */
+ 0, /* Will be set at runtime */
+ NULL /* Will be set at runtime */
+ }
+};
+
+struct read_info {
+ struct buf *bp; /* buffer for strategy function */
+ long nbytes; /* total number of bytes to read */
+ long offset; /* offset in input medium */
+ caddr_t bufp; /* current output buffer */
+ caddr_t ebufp; /* absolute maximum for bufp */
+ int chunk; /* chunk size on input medium */
+ int media_sz; /* size of input medium */
+ void (*strat)(); /* strategy function for read */
+};
+
+/*
+ * Autoconfig stuff....
+ */
+static int ramdmatch __P((struct device *, struct cfdata *, void *));
+static int ramdprint __P((void *, char *));
+static void ramdattach __P((struct device *, struct device *, void *));
+
+struct cfdriver ramdcd = {
+ NULL, "rd", (cfmatch_t)ramdmatch, ramdattach, DV_DULL,
+ sizeof(struct device), NULL, 0 };
+
+static int
+ramdmatch(pdp, cfp, auxp)
+struct device *pdp;
+struct cfdata *cfp;
+void *auxp;
+{
+ if(strcmp("rd", auxp) || (cfp->cf_unit >= RAMD_NDEV))
+ return(0);
+ return(1);
+}
+
+static void
+ramdattach(pdp, dp, auxp)
+struct device *pdp, *dp;
+void *auxp;
+{
+ int i;
+
+ for(i = 0; i < RAMD_NDEV; i++)
+ config_found(dp, (void*)i, ramdprint);
+}
+
+static int
+ramdprint(auxp, pnp)
+void *auxp;
+char *pnp;
+{
+ return(UNCONF);
+}
+
+static int loaddisk __P((struct ramd_info *, struct proc *));
+static int ramd_norm_read __P((struct read_info *));
+static int cpy_uncompressed __P((caddr_t, int, struct read_info *));
+static int rd_compressed __P((caddr_t, int, struct read_info *));
+
+int
+rdopen(dev, flags, devtype, p)
+dev_t dev;
+int flags, devtype;
+struct proc *p;
+{
+ struct ramd_info *ri;
+ int s;
+ int error = 0;
+
+ if(DISKUNIT(dev) >= RAMD_NDEV)
+ return(ENXIO);
+
+ ri = &rd_info[DISKUNIT(dev)];
+ if(ri->ramd_state & RAMD_OPEN)
+ return(0);
+
+ /*
+ * If someone is busy opening, wait for it to complete.
+ */
+ s = splbio();
+ while(ri->ramd_state & RAMD_INOPEN) {
+ ri->ramd_state |= RAMD_WANTED;
+ tsleep((caddr_t)ri, PRIBIO, "rdopen", 0);
+ }
+ ri->ramd_state |= RAMD_INOPEN;
+ splx(s);
+
+ if(!(ri->ramd_state & RAMD_ALLOC)) {
+ ri->ramd_addr = malloc(ri->ramd_size, M_DEVBUF, M_WAITOK);
+ if(ri->ramd_addr == NULL) {
+ error = ENXIO;
+ goto done;
+ }
+ ri->ramd_state |= RAMD_ALLOC;
+ }
+ if((ri->ramd_flag & RAMD_LOAD) && !(ri->ramd_state & RAMD_LOADED)) {
+ error = loaddisk(ri, p);
+ if(!error)
+ ri->ramd_state |= RAMD_LOADED;
+ }
+done:
+ ri->ramd_state &= ~RAMD_INOPEN;
+ if(ri->ramd_state & RAMD_WANTED) {
+ ri->ramd_state &= ~RAMD_WANTED;
+ wakeup((caddr_t)ri);
+ }
+ return(error);
+}
+
+int
+rdclose(dev, flags, devtype, p)
+dev_t dev;
+int flags, devtype;
+struct proc *p;
+{
+ return(0);
+}
+
+int
+rdioctl(dev, cmd, addr, flag, p)
+dev_t dev;
+u_long cmd;
+int flag;
+caddr_t addr;
+struct proc *p;
+{
+ return(ENOTTY);
+}
+
+/*
+ * no dumps to ram disks thank you.
+ */
+int
+rdsize(dev)
+dev_t dev;
+{
+ return(-1);
+}
+
+void
+rdstrategy(bp)
+struct buf *bp;
+{
+ struct ramd_info *ri;
+ long maxsz, sz;
+ char *datap;
+
+ ri = &rd_info[DISKUNIT(bp->b_dev)];
+
+ maxsz = ri->ramd_size / DEV_BSIZE;
+ sz = (bp->b_bcount + DEV_BSIZE - 1) / DEV_BSIZE;
+ if (bp->b_blkno < 0 || bp->b_blkno + sz > maxsz) {
+ if((bp->b_blkno == maxsz) && (bp->b_flags & B_READ)) {
+ /* Hitting EOF */
+ bp->b_resid = bp->b_bcount;
+ goto done;
+ }
+ sz = maxsz - bp->b_blkno;
+ if((sz <= 0) || (bp->b_blkno < 0)) {
+ bp->b_error = EINVAL;
+ bp->b_flags |= B_ERROR;
+ goto done;
+ }
+ bp->b_bcount = sz * DEV_BSIZE;
+ }
+ datap = (char*)((u_long)ri->ramd_addr + bp->b_blkno * DEV_BSIZE);
+ if(bp->b_flags & B_READ)
+ bcopy(datap, bp->b_data, bp->b_bcount);
+ else bcopy(bp->b_data, datap, bp->b_bcount);
+ bp->b_resid = 0;
+ biodone(bp);
+ return;
+
+done:
+ bp->b_resid = bp->b_bcount;
+ biodone(bp);
+}
+
+int
+rdread(dev, uio)
+dev_t dev;
+struct uio *uio;
+{
+ return (physio(rdstrategy, NULL, dev, B_READ, minphys, uio));
+}
+
+int
+rdwrite(dev, uio)
+dev_t dev;
+struct uio *uio;
+{
+ return (physio(rdstrategy, NULL, dev, B_WRITE, minphys, uio));
+}
+
+static int
+loaddisk(ri, proc)
+struct ramd_info *ri;
+struct proc *proc;
+{
+ struct buf buf;
+ int error;
+ struct bdevsw *bdp = &bdevsw[major(ri->ramd_dev)];
+ struct disklabel dl;
+ struct read_info rs;
+
+ /*
+ * Initialize out buffer header:
+ */
+ buf.b_actf = NULL;
+ buf.b_rcred = buf.b_wcred = proc->p_ucred;
+ buf.b_vnbufs.le_next = NOLIST;
+ buf.b_flags = B_BUSY;
+ buf.b_dev = ri->ramd_dev;
+ buf.b_error = 0;
+ buf.b_proc = proc;
+
+ /*
+ * Setup read_info:
+ */
+ rs.bp = &buf;
+ rs.nbytes = ri->ramd_size;
+ rs.offset = 0;
+ rs.bufp = ri->ramd_addr;
+ rs.ebufp = ri->ramd_addr + ri->ramd_size;
+ rs.chunk = RAMD_CHUNK;
+ rs.media_sz = ri->ramd_size;
+ rs.strat = bdp->d_strategy;
+
+ /*
+ * Open device and try to get some statistics.
+ */
+ if(error = bdp->d_open(ri->ramd_dev,FREAD | FNONBLOCK, 0, proc))
+ return(error);
+ if(bdp->d_ioctl(ri->ramd_dev,DIOCGDINFO,(caddr_t)&dl,FREAD,proc) == 0) {
+ /* Read on a cylinder basis */
+ rs.chunk = dl.d_secsize * dl.d_secpercyl;
+ rs.media_sz = dl.d_secperunit * dl.d_secsize;
+ }
+
+#ifdef notyet
+ if(ri->ramd_flag & RAMD_LCOMP)
+ error = decompress(cpy_uncompressed, rd_compressed, &rs);
+ else
+#endif /* notyet */
+ error = ramd_norm_read(&rs);
+
+ bdp->d_close(ri->ramd_dev,FREAD | FNONBLOCK, 0, proc);
+ return(error);
+}
+
+static int
+ramd_norm_read(rsp)
+struct read_info *rsp;
+{
+ long bytes_left;
+ int done, error;
+ struct buf *bp;
+ int s;
+ int dotc = 0;
+
+ bytes_left = rsp->nbytes;
+ bp = rsp->bp;
+ error = 0;
+
+ while(bytes_left > 0) {
+ s = splbio();
+ bp->b_flags = B_BUSY | B_PHYS | B_READ;
+ splx(s);
+ bp->b_blkno = btodb(rsp->offset);
+ bp->b_bcount = rsp->chunk;
+ bp->b_data = rsp->bufp;
+
+ /* Initiate read */
+ (*rsp->strat)(bp);
+
+ /* Wait for results */
+ s = splbio();
+ while ((bp->b_flags & B_DONE) == 0)
+ tsleep((caddr_t) bp, PRIBIO + 1, "ramd_norm_read", 0);
+ if (bp->b_flags & B_ERROR)
+ error = (bp->b_error ? bp->b_error : EIO);
+ splx(s);
+
+ /* Dot counter */
+ printf(".");
+ if(!(++dotc % 40))
+ printf("\n");
+
+ done = bp->b_bcount - bp->b_resid;
+ bytes_left -= done;
+ rsp->offset += done;
+ rsp->bufp += done;
+
+ if(error || !done)
+ break;
+
+ if((rsp->offset == rsp->media_sz) && (bytes_left != 0)) {
+ printf("\nInsert next media and hit any key...");
+ cngetc();
+ printf("\n");
+ rsp->offset = 0;
+ }
+ }
+ printf("\n");
+ s = splbio();
+ splx(s);
+ return(error);
+}
+
+/*
+ * Functions supporting uncompression:
+ */
+/*
+ * Copy from the uncompression buffer to the ramdisk
+ */
+static int
+cpy_uncompressed(buf, nbyte, rsp)
+caddr_t buf;
+struct read_info *rsp;
+int nbyte;
+{
+ if((rsp->bufp + nbyte) >= rsp->ebufp)
+ return(0);
+ bcopy(buf, rsp->bufp, nbyte);
+ rsp->bufp += nbyte;
+ return(0);
+}
+
+/*
+ * Read a maximum of 'nbyte' bytes into 'buf'.
+ */
+static int
+rd_compressed(buf, nbyte, rsp)
+caddr_t buf;
+struct read_info *rsp;
+int nbyte;
+{
+ static int dotc = 0;
+ struct buf *bp;
+ int nread = 0;
+ int s;
+ int done, error;
+
+
+ error = 0;
+ bp = rsp->bp;
+ nbyte &= ~(DEV_BSIZE - 1);
+
+ while(nbyte > 0) {
+ s = splbio();
+ bp->b_flags = B_BUSY | B_PHYS | B_READ;
+ splx(s);
+ bp->b_blkno = btodb(rsp->offset);
+ bp->b_bcount = min(rsp->chunk, nbyte);
+ bp->b_data = buf;
+
+ /* Initiate read */
+ (*rsp->strat)(bp);
+
+ /* Wait for results */
+ s = splbio();
+ while ((bp->b_flags & B_DONE) == 0)
+ tsleep((caddr_t) bp, PRIBIO + 1, "ramd_norm_read", 0);
+ if (bp->b_flags & B_ERROR)
+ error = (bp->b_error ? bp->b_error : EIO);
+ splx(s);
+
+ /* Dot counter */
+ printf(".");
+ if(!(++dotc % 40))
+ printf("\n");
+
+ done = bp->b_bcount - bp->b_resid;
+ nbyte -= done;
+ nread += done;
+ rsp->offset += done;
+
+ if(error || !done)
+ break;
+
+ if(rsp->offset == rsp->media_sz) {
+ printf("\nInsert next media and hit any key...");
+ if(cngetc() != '\n')
+ printf("\n");
+ rsp->offset = 0;
+ }
+ }
+ s = splbio();
+ splx(s);
+ return(nread);
+}