/* $NetBSD: md_root.c,v 1.6 1996/10/11 00:09:34 christos Exp $ */ /* * Copyright (c) 1996 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* * 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 */ }; /* * ramd_flag: */ #define RAMD_LOAD 0x01 /* Auto load when first opened */ #define RAMD_LCOMP 0x02 /* Input is compressed */ 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) */ }, { 1474560, /* 1.44Mb in 2880 sectors */ RAMD_LOAD, /* auto-load this device */ MAKEDISKDEV(2, 0, 1), /* XXX: This is crap! (720Kb flop) */ } }; 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)(struct buf *); /* strategy function for read */ }; static int loaddisk __P((struct rd_conf *, dev_t ld_dev, struct proc *)); static int ramd_norm_read __P((struct read_info *)); #ifdef support_compression static int cpy_uncompressed __P((caddr_t, int, struct read_info *)); static int rd_compressed __P((caddr_t, int, struct read_info *)); #endif /* * This is called during autoconfig. */ void rd_attach_hook(unit, rd) int unit; struct rd_conf *rd; { if (atari_realconfig && (unit < RAMD_NDEV) && rd_info[unit].ramd_flag) { kprintf ("rd%d:%sauto-load on open. Size %ld bytes.\n", unit, rd_info[unit].ramd_flag & RAMD_LCOMP ? " decompress/" : "", rd_info[unit].ramd_size); rd->rd_type = RD_UNCONFIGURED; /* Paranoia... */ } } void rd_open_hook(unit, rd) int unit; struct rd_conf *rd; { struct ramd_info *ri; if(unit >= RAMD_NDEV) return; ri = &rd_info[unit]; if (rd->rd_type != RD_UNCONFIGURED) return; /* Only configure once */ rd->rd_addr = malloc(ri->ramd_size, M_DEVBUF, M_WAITOK); rd->rd_size = ri->ramd_size; if(rd->rd_addr == NULL) return; if(ri->ramd_flag & RAMD_LOAD) { if (loaddisk(rd, ri->ramd_dev, curproc)) { free(rd->rd_addr, M_DEVBUF); rd->rd_addr = NULL; return; } } rd->rd_type = RD_KMEM_ALLOCATED; } static int loaddisk(rd, ld_dev, proc) struct rd_conf *rd; dev_t ld_dev; struct proc *proc; { struct buf buf; int error; struct bdevsw *bdp = &bdevsw[major(ld_dev)]; struct disklabel dl; struct read_info rs; /* * Initialize our 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 = ld_dev; buf.b_error = 0; buf.b_proc = proc; /* * Setup read_info: */ rs.bp = &buf; rs.nbytes = rd->rd_size; rs.offset = 0; rs.bufp = rd->rd_addr; rs.ebufp = rd->rd_addr + rd->rd_size; rs.chunk = RAMD_CHUNK; rs.media_sz = rd->rd_size; rs.strat = bdp->d_strategy; /* * Open device and try to get some statistics. */ if((error = bdp->d_open(ld_dev, FREAD | FNONBLOCK, 0, proc)) != 0) return(error); if(bdp->d_ioctl(ld_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 support_compression if(ri->ramd_flag & RAMD_LCOMP) error = decompress(cpy_uncompressed, rd_compressed, &rs); else #endif /* support_compression */ error = ramd_norm_read(&rs); bdp->d_close(ld_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 */ kprintf("."); if(!(++dotc % 40)) kprintf("\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)) { kprintf("\nInsert next media and hit any key..."); cngetc(); kprintf("\n"); rsp->offset = 0; } } kprintf("\n"); return(error); } #ifdef support_compression /* * 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 */ kprintf("."); if(!(++dotc % 40)) kprintf("\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) && (nbyte != 0)) { if(rsp->offset == rsp->media_sz) { kprintf("\nInsert next media and hit any key..."); if(cngetc() != '\n') kprintf("\n"); rsp->offset = 0; } } s = splbio(); splx(s); return(nread); } #endif /* support_compression */