chris@umcp-cs.UUCP (Chris Torek) (01/05/85)
: Run this shell script with "sh" not "csh" PATH=:/bin:/usr/bin:/usr/ucb export PATH all=FALSE if [ $1x = -ax ]; then all=TRUE fi /bin/echo 'Extracting README' sed 's/^X//' <<'//go.sysin dd *' >README [README: 4.2 changes to kernel & dump for mass driver: 5 Jan 1984, Chris Torek, University of Maryland.] Before you do ANYTHING ELSE, read this file CAREFULLY! This is the set of kernel changes needed to install the mass driver. The mass driver itself consists of two files, sys/h/drivio.h and sys/sys/dev_driv.c. What the mass driver *does* is allow asynchronous transfers. (See the manual page for more information.) Installing drivio.h and dev_driv.c is trivial; just plunk them down and edit conf/files to include ``sys/dev_driv.c optional driv''. (I put it in at the end, but it doesn't really matter where it is.) Modifying the existing source files to make the mass driver *work* and *be useful* is more difficult. First, SAVE COPIES OF ALL THE FILES THAT WILL BE MODIFIED. These are (if you don't bother deleting extraneous ``#include "../h/conf.h"''s): h/conf.h sys/vm_mem.c vaxmba/ht.c h/fs.h vax/conf.c vaxmba/mba.c h/param.h vax/machdep.c vaxmba/mt.c h/vmparam.h vax/ufs_machdep.c vaxuba/ts.c (Note that I have no changes for the tm driver. If you have a tm, you're on your own. The changes should be similar to (if not exactly the same as) those for the ts driver.) Some of these changes are ``frills''; that is, they aren't essential to the mass driver, but they sure don't hurt, and I think they are useful. Following the advice of a fellow netlander, I have provided context diffs from 4.2 distribution sources. HOWEVER, the diffs cannot be applied by machine (e.g., by Larry Wall's patch program), because SOME of the changes CANNOT be installed on a vanilla 4.2 system. (In fact, the mass driver source given here some two minor differences from mine: my csleep()s have been edited back to sleep()s for this copy; the bp->b_offset fields have been commented out.) In particular, unless you have the BRL ``csleep'' routine in your kernel, avoid changing any ``sleep'' calls to ``csleep''s. (Csleep is just ``commented sleep'', with an additional ``char *'' argument which is stuck into the p_slmsg field of a struct proc. You don't have this field, of course . . . .) I have tried to mark each set of changes as to which are necessary and which are not. However, a short description of the changes I made will probably be helpful. Basically, two things have been added to every character device: an optional ``d_mass'' routine and an optional ``d_bstrat'' routine. If the former is set, then the device is usable with the mass driver. For each transfer, the d_mass routine will be called on a buffer containing the setup information which would normally be given to the block device's strategy routine. The d_mass routine should perform any special actions required, and should trim the b_bcount field if necessary. (See the tsmass, htmass, or mtmass routines for examples of what needs to be done on a tape drive.) Right after the d_mass routine returns, the d_bstrat routine (which is presumably the same as the block device strategy routine) will be called to start the transfer. Buffers in use for asynchronous transfers will be set up such that the biodone() routine in ufs_bio.c will call the routine driviodone(). This examines the return information in the buffer and, if there is more work to do, calls the d_mass and d_bstrat routines again. This creates a problem for the existing UNIBUS and MASSBUSS drivers. Let's look at the ts driver as a specific example. When tsintr() is called, it sets um->um_tab.b_active to zero to indicate that the device is no longer active. After reading the device registers and doing any necessary buffer cleanup, it will (if there is another buffer in the queue) start another transfer right away by calling tsstart(), then returns. tsstart() sets um->um_tab.b_active, calling the device active. This works well enough in most cases. However, now that we have the mass driver doing its thing, the following sequence of events will occur. 1. tsintr() sets um->um_tab.b_active = 0 2. tsintr() calls biodone() 3. biodone() calls driviodone() 4. driviodone() calls tsstrategy() 5. tsstrategy() puts the transfer at the end of the queue and sees um->um_tab.b_active == 0, so calls tsstart() 6. We return back to tsintr(), which sees that the queue is not empty and calls tsstart(), clobbering the in-progress transfer and having other disastrous effects. Two solutions came immediately to mind: either have tsintr() check um->um_tab.b_active before doing its last tsstart(), or have tsintr() keep better track of the device activity. In other words, if the interupt service code isn't done yet, the device can be considered active, since any requests placed on the device queue will be serviced before tsintr() returns. (Actually only the first will, but it has the same effect.) I prefer the latter solution, for various reasons, so that is what I have done. Interestingly, this code is centralized for massbuss devices (with the interrupt code residing in vaxmba/mba.c) because there is only one global massbuss interrupt vector, rather than lots of little vectors for each device. Nearly the same changes as were made to tsintr() had to be made to mbaintr(), with some extra work required in mbstart() and mbustart(). Well, now we have a working mass driver, but there is still one problem: dump can't use it, because dump wants to write 10240 byte records on tapes, and the biggest buffers we can get from the buffer cache are 8192 bytes. This is easily fixed; just increase MAXBSIZE. (I set it to 16384.) But---that creates more problems of its own. First of all, it cuts the number of buffers, making them too scarce. After all, the ``average'' file system block is only about 4096 bytes long anyway; we should have enough buffers for those, rather than for 16384 byte blocks. Solution: create an AVGBSIZE define in param.h, and make the buffer allocation code use this. Of course, that made me look at the virtual memory setup code in vax/machdep.c, which I just HAD to change all around :-), which led to making changes in sys/vm_mem.c. It turns out that as distributed, both 4.1 and 4.2 will not run on a system with ``lots'' of memory, panic("sys pt too small")ing. This is silly. If there is enough memory to map the kernel and SOME user area, then that should be done, with the system in ``limp mode'' until the kernel is recompiled with a bigger SYSPTSIZE. I've changed the startup code to notice slightly small or ridiculously large SYSPTSIZEs and complain. Of course, with all that extra virtual memory needed to map 16384 byte buffers, I had to increase SYSPTSIZE (in vax/vmparam.h). That covers every file but one: vax/ufs_machdep.c. All I did there was add a panic if the buffer size requested is > MAXBSIZE. I made that mistake the first time . . . . (The change to h/fs.h is merely to fix a comment; vax/conf.c needs to be changed because all the character devices need two more entries. Ok, so it covered every file but two.) There is one other thing you can do while you're editing half your kernel, though it's not important. Far too many files needlessly include ../h/conf.h. A partial list of these files is given in the file ``needless_conf.h''. If you're feeling particularly ambitious, now is a good time to remove those includes, since everything is going to get recompiled anyway. Now that you've read all that, 1) Install the drivio.h and dev_driv.c files and edit conf/files. 2) Make kernel modifications as indicated in kernel_mods. Don't forget to add the entry for the mass driver in vax/conf.c, and do remember what it's major device number is. 3) Put a ``pseudo-device driv'' in your config file. 4) Configure and compile a new kernel. 5) Test the kernel to make sure it still works at all. And for dump: 1) Install the changes given in dump_mods. (I'm sorry it's so long; I fixed the formatting of lots of ``if(x) {''s or ``while (y){''s which makes the diff listing a lot longer than it really needs to be.) All the non-mass-driver related changes in dump are from the net (one from M. Kirk McKusick @ Berkeley, one from Donn Seely @ Utah-CS, and one from ?(I forget) @ U of Waterloo, as I recall). 2) Compile, fix typos :-). (Actually, I bet patch would work.) 3) Make a /dev/driv0 with the right major device number (minor == 0). You may want to restrict access to it. 4) Try ``dump <dump_options>m <regular dump stuff>'', e.g., dump 0m /, to make sure the mass driver works. 5) Edit the manual entry to note the new ``m'' key for invoking the mass driver. //go.sysin dd * made=TRUE if [ $made = TRUE ]; then /bin/chmod 644 README /bin/echo -n ' '; /bin/ls -ld README fi /bin/echo 'Extracting dev_driv.c' sed 's/^X//' <<'//go.sysin dd *' >dev_driv.c #ifndef lint static char rcsid[] = "$Header: /usr/sys/sys/RCS/dev_driv.c,v 1.3 85/01/03 12:27:49 chris Exp $"; #endif lint X/* * dev_driv.c ("mass driver") * Chris Torek, U of Maryland * Pseudo-driver for running other devices asynchronously * * Copyright (c) 1985, all rights reserved. The right to distribute this * code is explicitly granted if and only if 1) no changes are made, or * 2) all changes are clearly marked (e.g., via #ifdef/#endif). (All I'm * trying to do here is make sure my name doesn't get sent around on some * piece of code I never wrote. OK? PLEEEEZE??? :-) ) * * This pseudo driver allows one to read and write a device without * waiting for the transfer(s) to complete. It calls the device's (block) * strategy routine directly. We only run with specially-prepared * drivers, however: there is a new routine (d_mass) we use as a * combination of "minphys" and a catch-all for anything else that must be * done before starting a transfer, and there must be a strategy routine * in the character switch entry. Note that we also deal in transfers of * other than BLKDEV_IOSIZE bytes. * * An initial ioctl() sets up the maximum number and size of transfers. * Space is stolen from the buffer pool (but never more than half * of the real buffer pool may be in use). When the pseudo-driver * is read or written, the data is copied in to kernel space and * we start (but do not wait for) the real transfer. * * (READ IS NOT DONE YET) * For read()s, an ioctl() can be used to start a transfer. Later * (when select() says it's OK) a read() will grab the data. * * For write()s, the transfer is started after copying from user * space. Select() will succeed when the write is done. * * In any case, an ioctl() is used to get the final return value * (consisting of a real return value and an error code). Another * ioctl() can be used to wait for all pending transfers to complete. * * We shamelessly use the (otherwise useless to us) b_proc field of the * buffers to hold the info we need when our iodone routine is called. * * Problem: since kernel buffer space is allocated based on MAXBSIZE * as the maximum amount of kernel space in any one ``struct buf'', * that is the largest transfer size we can handle as well. * * TODO: * - Write read() code * - Stop transfers at error (provide ioctl to clear error condition?) * - Learn why we sometimes hang before closing when using MAX_XFERS */ #include "driv.h" #if NDRIV > 0 #include "../h/param.h" #include "../h/systm.h" #include "../h/buf.h" #include "../h/inode.h" #include "../h/file.h" #include "../h/dir.h" #include "../h/user.h" #include "../h/proc.h" #include "../h/uio.h" #include "../h/ioctl.h" #include "../h/conf.h" #include "../h/errno.h" #include "../h/drivio.h" X/* one of the hard limits (the other is MAXBSIZE) */ #define MAX_XFERS 25 /* max # of pending transfers */ X/* * The xfer structure is used to hold all the info needed about ongoing * and completed transfers. * N.B.: Assumes MAXBSIZE fits in an "int". */ struct xfer { struct buf *xf_buf; /* buffer */ struct driv_softc *xf_sc;/* backpointer to driver info */ caddr_t xf_addr; /* base of original transfer */ short xf_rw; /* B_READ or B_WRITE */ short xf_error; /* error number (if any) */ off_t xf_offset; /* position at start of transfer */ int xf_bcount; /* original byte count */ int xf_resid; /* remaining byte count */ int xf_xcount; /* bp->b_bcount, in case it gets munched */ int xf_rval; /* return value */ }; struct driv_softc { short sc_flags; /* state info */ dev_t sc_dev; /* device to which to refer */ struct file *sc_fp; /* user file descriptor to manipulate */ int sc_xsize; /* amount of memory allocated per xfer */ short sc_max_xfers; /* max # of pending transfers */ short sc_pend; /* number of pending transfers */ short sc_nxx; /* index of next transfer */ short sc_rxx; /* index of next return val */ short sc_valid; /* number of valid return values */ struct xfer sc_xf[MAX_XFERS];/* transfer info */ struct proc *sc_sel; /* process selecting */ } driv_softc[NDRIV]; #define DRIV_OPEN 0x01 /* open */ #define DRIV_DEV 0x02 /* have sc_dev info etc. */ #define DRIV_WANT 0x04 /* wakeup() when I/O is done */ #define DRIV_SELCOLL 0x08 /* select() collision */ #define PDRIV (PZERO-1) /* priority for sleep() on buffers */ extern int bufpages; /* tells us how big the buffer pool is */ int drivpages; /* total number of pages stolen from the buffer pool at the moment */ extern int nbuf; /* how many buffers are there? */ int drivbufs; /* how many do we have? */ X/* * Open the pseudo-driver */ X/*ARGSUSED*/ drivopen(dev, flag) dev_t dev; int flag; { register struct driv_softc *sc = &driv_softc[minor(dev)]; if (sc->sc_flags & DRIV_OPEN) return (EBUSY); sc->sc_flags = DRIV_OPEN; sc->sc_max_xfers = 0; sc->sc_xsize = 0; sc->sc_pend = 0; sc->sc_nxx = 0; sc->sc_rxx = 0; sc->sc_valid = 0; return (0); } X/* * Close the pseudo-driver */ X/*ARGSUSED*/ drivclose(dev, flag) dev_t dev; int flag; { register struct driv_softc *sc = &driv_softc[minor(dev)]; if (sc->sc_flags & DRIV_DEV) { drivfree(sc); closef(sc->sc_fp); } sc->sc_flags = 0; } X/* * Read. We don't do this yet... */ X/*ARGSUSED*/ drivread(dev, uio) dev_t dev; struct uio *uio; { return (EOPNOTSUPP); /* XXX */ } X/* * Write. Dump the user's write stuff into our buffer, then start * things rolling. */ drivwrite(dev, uio) dev_t dev; register struct uio *uio; { register struct driv_softc *sc = &driv_softc[minor(dev)]; register struct xfer *xf; int s, error; if ((sc->sc_flags & DRIV_DEV) == 0) return (EINVAL); if ((sc->sc_fp->f_flag & FWRITE) == 0) return (EBADF); if (sc->sc_xsize < uio->uio_resid) return (ENOMEM); s = spl6(); while (sc->sc_pend >= sc->sc_max_xfers) { sc->sc_flags |= DRIV_WANT; sleep((caddr_t)sc, PDRIV); } splx(s); xf = &sc->sc_xf[sc->sc_nxx++]; if (sc->sc_nxx >= sc->sc_max_xfers) sc->sc_nxx = 0; if (xf->xf_addr == NULL) panic("drivwrite"); xf->xf_offset = uio->uio_offset; error = uiomove(xf->xf_addr, xf->xf_bcount = uio->uio_resid, UIO_WRITE, uio); if (error) return (error); drivstart(xf, B_WRITE); return (0); } X/* * Handle an ioctl. */ drivioctl(dev, cmd, data, flag) dev_t dev; int cmd; register caddr_t data; int flag; { register struct driv_softc *sc = &driv_softc[minor(dev)]; switch (cmd) { case DIOCSETINFO: { /* set device info */ register struct file *fp; register struct inode *ip; int nxfer; #define d ((struct diocinfo *)data) if (sc->sc_flags & DRIV_DEV) return (EINVAL);/* EEXIST? */ nxfer = d->dioc_nxfer > MAX_XFERS ? MAX_XFERS : d->dioc_nxfer; if (d->dioc_xsize < 1 || nxfer < 1) return (EINVAL); if (d->dioc_xsize > MAXBSIZE) return (ENOSPC);/* sort of */ fp = getf(d->dioc_fd); if (fp == NULL) return (EBADF); if (fp->f_type != DTYPE_INODE) return (EINVAL); ip = (struct inode *)fp->f_data; if ((ip->i_mode & IFMT) != IFCHR || cdevsw[major((dev_t)ip->i_rdev)].d_mass == NULL) return (EINVAL); fp->f_count++; /* prevent user from close()ing */ if (drivalloc(sc, d->dioc_xsize, nxfer)) { closef(fp); return (ENOMEM); } sc->sc_flags |= DRIV_DEV; sc->sc_fp = fp; sc->sc_dev = (dev_t)ip->i_rdev; sc->sc_xsize = d->dioc_xsize; sc->sc_max_xfers = nxfer; break; #undef d } case DIOCREAD: /* start a read */ return (EOPNOTSUPP);/* XXX */ case DIOCGETRET: { /* get return value */ register struct xfer *xf; #define d ((struct diocret *)data) if (sc->sc_valid == 0) return (ENOENT);/* well, sorta */ xf = &sc->sc_xf[sc->sc_rxx++]; if (sc->sc_rxx >= sc->sc_max_xfers) sc->sc_rxx = 0; sc->sc_valid--; d->dioc_rval = xf->xf_rval; d->dioc_error = xf->xf_error; break; #undef d } case DIOCWAIT: { /* wait for pending transfers */ register int s = spl6(); while (sc->sc_pend) { sc->sc_flags |= DRIV_WANT; sleep((caddr_t)sc, PZERO+1); } splx(s); /* == spl0()? */ break; } case DIOCGMAXX: /* get max # transfers */ *(int *)data = (sc->sc_flags & DRIV_DEV) ? sc->sc_max_xfers : MAX_XFERS; break; default: return (ENOTTY); } return (0); } X/* * Select. */ drivselect(dev, rw) dev_t dev; int rw; { register struct driv_softc *sc = &driv_softc[minor(dev)]; int s = spl6(); switch (rw) { case FREAD: return (1); /* XXX */ case FWRITE: if (sc->sc_valid) { splx(s); return (1); } if (sc->sc_sel && sc->sc_sel->p_wchan == (caddr_t)&selwait) sc->sc_flags |= DRIV_SELCOLL; else sc->sc_sel = u.u_procp; splx(s); return (0); default: splx(s); return (0); } /*NOTREACHED*/ } X/* * Start a transfer. Fill in all the buffer fields and some of the xf * fields, and make sure the device is active. */ drivstart(xf, rw) register struct xfer *xf; int rw; { register struct driv_softc *sc = xf->xf_sc; register struct buf *bp = xf->xf_buf; int s, driviodone(); if (bp == NULL) /* just in case... */ panic("drivstart bp"); if (sc == NULL) panic("drivstart sc"); if (bp->b_flags & B_BUSY) panic("drivstart B_BUSY"); bp->b_un.b_addr = xf->xf_addr;/* set buffer address */ xf->xf_resid = xf->xf_bcount; xf->xf_rw = rw; s = spl6(); if (sc->sc_pend++) { /* already active */ splx(s); return; } splx(s); drivgo(sc->sc_dev, bp, xf); } X/* * Fill in the buffer fields and call the strategy routine. */ drivgo(dev, bp, xf) dev_t dev; register struct buf *bp; register struct xfer *xf; { register struct cdevsw *d = &cdevsw[major(dev)]; int driviodone(); bp->b_proc = (struct proc *)xf;/* ick */ bp->b_error = 0; bp->b_iodone = driviodone; bp->b_flags = B_BUSY | B_CALL | xf->xf_rw; bp->b_dev = dev; X/* bp->b_offset = xf->xf_offset; /* BRL */ bp->b_blkno = btodb(xf->xf_offset); bp->b_bcount = xf->xf_resid; (*d->d_mass)(bp); xf->xf_xcount = bp->b_bcount; (*d->d_bstrat)(bp); } X/* * The transfer involving this buffer is done. If there is more work * to do, fill in the buffer info and restart the transfer. Otherwise, * wake up anyone sleeping on the buffer or the transfer, and wake up * anyone doing select()s, then if there are more transfers pending, * fire up the next one. */ driviodone(bp) register struct buf *bp; { register struct xfer *xf = (struct xfer *)bp->b_proc;/* ick */ register struct driv_softc *sc; register int c; sc = xf->xf_sc; c = xf->xf_xcount - bp->b_resid; xf->xf_resid -= c; xf->xf_offset += c; if (xf->xf_resid > 0) { /* more to do */ /* temp kludge for tape drives */ if (bp->b_resid || (bp->b_flags&B_ERROR)) goto done; bp->b_un.b_addr += c; /* advance */ drivgo(sc->sc_dev, bp, xf); return; } done: if (bp->b_flags & B_WANTED) wakeup((caddr_t)bp); bp->b_flags &= ~(B_BUSY|B_WANTED); if (sc->sc_flags & DRIV_WANT) { wakeup((caddr_t)sc); sc->sc_flags &= ~DRIV_WANT; } xf->xf_rval = xf->xf_bcount - xf->xf_resid; xf->xf_error = geterror(bp); sc->sc_valid++; if (sc->sc_valid > sc->sc_max_xfers) {/* user just lost a return val */ sc->sc_valid--; if (++sc->sc_rxx >= sc->sc_max_xfers) sc->sc_rxx = 0; } if (sc->sc_sel) { selwakeup(sc->sc_sel, sc->sc_flags & DRIV_SELCOLL); sc->sc_sel = NULL; } if (--sc->sc_pend > 0) { /* start the next one */ c = (xf - sc->sc_xf) + 1; if (c >= sc->sc_max_xfers) c = 0; xf = &sc->sc_xf[c]; bp = xf->xf_buf; if (bp == NULL) panic("driviodone bp"); drivgo(sc->sc_dev, bp, xf); } } X/* * Allocate enough buffer space for the given totals, but not if * it would take too many buffers or too much memory. Fill in the * xf_addr fields. To be nice to the paging system, we round up * to CLBYTES, though it's not supposed to be necessary. */ drivalloc(sc, xsize, nxfer) register struct driv_softc *sc; register int xsize, nxfer; { register int i; register struct xfer *xf; if ((drivbufs + nxfer) >= (nbuf >> 1)) return (-1); xsize = roundup(xsize, CLBYTES); i = xsize / CLBYTES * nxfer + drivpages; if (i >= (bufpages >> 1)) return (-1); drivbufs += nxfer; drivpages = i; for (i = 0, xf = sc->sc_xf; i < nxfer; i++, xf++) { xf->xf_buf = geteblk(xsize); xf->xf_buf->b_flags &= ~B_BUSY; /* tyke it awye! */ xf->xf_addr = xf->xf_buf->b_un.b_addr;/* save buffer addr */ xf->xf_sc = sc; } return (0); } X/* * Free the attached buffers, zapping the xf pointers so as to detect * bugs early. */ drivfree(sc) register struct driv_softc *sc; { register int i; register struct xfer *xf; register struct buf *bp; i = spl6(); while (sc->sc_pend) { sc->sc_flags |= DRIV_WANT; sleep((caddr_t)sc, PDRIV); } splx(i); for (i = 0, xf = sc->sc_xf; i < sc->sc_max_xfers; i++, xf++) { if ((bp = xf->xf_buf) == NULL) panic("drivfree"); drivpages -= bp->b_bufsize / CLBYTES; drivbufs--; /* return it in its original condition */ bp->b_dev = NODEV; bp->b_flags = B_BUSY|B_INVAL; bp->b_un.b_addr = xf->xf_addr; bp->b_bcount = bp->b_bufsize; brelse(bp); xf->xf_buf = NULL; xf->xf_addr = NULL; xf->xf_sc = NULL; } } #endif NDRIV > 0 //go.sysin dd * made=TRUE if [ $made = TRUE ]; then /bin/chmod 644 dev_driv.c /bin/echo -n ' '; /bin/ls -ld dev_driv.c fi /bin/echo 'Extracting drivio.h' sed 's/^X//' <<'//go.sysin dd *' >drivio.h X/* $Header: /usr/sys/h/RCS/drivio.h,v 1.1 85/01/02 09:44:05 chris Exp $ */ X/* * diocinfo contains the information needed to initialize the hyperdriver */ struct diocinfo { int dioc_fd; /* file descriptor */ int dioc_xsize; /* max size of any one transfer */ int dioc_nxfer; /* max number of uncompleted transfers */ }; X/* * diocret contains the return status information for completed transfers */ struct diocret { int dioc_rval; /* return value */ int dioc_error; /* error number */ }; #define DIOCSETINFO _IOW(D, 0, struct diocinfo) /* set info */ #define DIOCREAD _IO(D, 1) /* start a read */ #define DIOCGETRET _IOR(D, 2, struct diocret) /* get return info */ #define DIOCWAIT _IO(D, 3) /* wait for I/O to finish */ #define DIOCGMAXX _IOR(D, 4, int) /* get max # xfers */ //go.sysin dd * made=TRUE if [ $made = TRUE ]; then /bin/chmod 644 drivio.h /bin/echo -n ' '; /bin/ls -ld drivio.h fi /bin/echo 'Extracting dump_mods' sed 's/^X//' <<'//go.sysin dd *' >dump_mods RCS file: RCS/dump.h,v retrieving revision 1.1 diff -c1 -r1.1 dump.h *** /tmp/,RCSt1005006 Sat Jan 5 03:22:00 1985 --- dump.h Sun Dec 30 07:34:11 1984 *************** *** 69,70 int dump(); int tapsrec(); --- 69,71 ----- int dump(); + int dirdump(); int tapsrec(); RCS file: RCS/dumpitime.c,v retrieving revision 1.1 diff -c1 -r1.1 dumpitime.c *** /tmp/,RCSt1005011 Sat Jan 5 03:22:06 1985 --- dumpitime.c Sun Dec 30 07:34:12 1984 *************** *** 206,209 * This is an estimation of the number of TP_BSIZE blocks in the file. ! * It assumes that there are no unallocated blocks; hence ! * the estimate may be high */ --- 206,209 ----- * This is an estimation of the number of TP_BSIZE blocks in the file. ! * WARNING: it uses the di_blocks field of the inode, which is not ! * maintained in 4.1c BSD. */ *************** *** 212,214 { ! long s; --- 212,214 ----- { ! long s, t; *************** *** 215,218 esize++; ! /* calc number of TP_BSIZE blocks */ ! s = howmany(ip->di_size, TP_BSIZE); if (ip->di_size > sblock->fs_bsize * NDADDR) { --- 215,236 ----- esize++; ! ! /* ! * ip->di_size is the size of the file in bytes. ! * ip->di_blocks stores the number of sectors actually in the file. ! * If there are more sectors than the size would indicate, this just ! * means that there are unused sectors in the last file block; ! * we can safely ignore these (s = t below). ! * If the file is bigger than the number of sectors would indicate, ! * then the file has holes in it. In this case we must use the ! * block count for keeping track of actual blocks used, but we ! * use the actual size for estimating the number of indirect ! * blocks (t vs. s in the indirect block calculations) -- this ! * is simply because dump fills in holes in indirect blocks, ! * so the di_blocks field (which already counts the indirect ! * blocks) can't be used directly. ! */ ! s = howmany(dbtob(ip->di_blocks), TP_BSIZE); ! t = howmany(ip->di_size, TP_BSIZE); ! if (s > t) ! s = t; if (ip->di_size > sblock->fs_bsize * NDADDR) { *************** *** 218,221 if (ip->di_size > sblock->fs_bsize * NDADDR) { ! /* calc number of indirect blocks on the dump tape */ ! s += howmany(s - NDADDR * sblock->fs_bsize / TP_BSIZE, TP_NINDIR); --- 236,239 ----- if (ip->di_size > sblock->fs_bsize * NDADDR) { ! /* calculate the number of indirect blocks on the dump tape */ ! s += howmany(t - NDADDR * sblock->fs_bsize / TP_BSIZE, TP_NINDIR); RCS file: RCS/dumpmain.c,v retrieving revision 1.1 diff -c1 -r1.1 dumpmain.c *** /tmp/,RCSt1005016 Sat Jan 5 03:22:14 1985 --- dumpmain.c Mon Dec 31 23:06:55 1984 *************** *** 9,10 int cartridge = 0; /* Assume non-cartridge tape */ #ifdef RDUMP --- 9,11 ----- int cartridge = 0; /* Assume non-cartridge tape */ + int mass_driver = 0;/* use mass driver */ #ifdef RDUMP *************** *** 36,38 arg = "u"; ! if(argc > 1) { argv++; --- 37,39 ----- arg = "u"; ! if (argc > 1) { argv++; *************** *** 43,45 } ! while(*arg) switch (*arg++) { --- 44,46 ----- } ! while (*arg) switch (*arg++) { *************** *** 55,57 case 'f': /* output file */ ! if(argc > 1) { argv++; --- 56,58 ----- case 'f': /* output file */ ! if (argc > 1) { argv++; *************** *** 71,73 case 's': /* tape size, feet */ ! if(argc > 1) { argv++; --- 72,74 ----- case 's': /* tape size, feet */ ! if (argc > 1) { argv++; *************** *** 80,82 case 'b': /* blocks per tape write */ ! if(argc > 1) { argv++; --- 81,83 ----- case 'b': /* blocks per tape write */ ! if (argc > 1) { argv++; *************** *** 112,113 default: --- 113,118 ----- + case 'm': + mass_driver++; /* the accelerator... */ + break; + default: *************** *** 116,118 } ! if(argc > 1) { argv++; --- 121,123 ----- } ! if (argc > 1) { argv++; *************** *** 267,269 msg("dumping (Pass III) [directories]\n"); ! pass(dump, dirmap); --- 272,274 ----- msg("dumping (Pass III) [directories]\n"); ! pass(dirdump, dirmap); RCS file: RCS/dumptape.c,v retrieving revision 1.1 diff -c1 -r1.1 dumptape.c *** /tmp/,RCSt1005040 Sat Jan 5 03:23:00 1985 --- dumptape.c Mon Dec 31 23:40:23 1984 *************** *** 2,3 #include "dump.h" --- 2,6 ----- #include "dump.h" + #include <sys/ioctl.h> + #include <sys/drivio.h> + #include <errno.h> *************** *** 7,8 extern int ntrec; /* blocking factor on tape */ --- 10,12 ----- extern int ntrec; /* blocking factor on tape */ + extern int mass_driver; /* true => should use mass driver */ *************** *** 8,9 /* --- 12,19 ----- + int wr_pend; /* number of pending writes */ + int wr_maxpend; /* max allowable # of pending writes */ + int WR_MAX = 0; /* patchable, can set max we will use */ + int drivfd = -1; /* driver fd */ + extern int errno; + /* *************** *** 29,31 { - register i; --- 39,40 ----- { *************** *** 31,34 ! for (i=0; i < TP_BSIZE; i++) ! tblock[trecno][i] = *dp++; trecno++; --- 40,42 ----- ! bcopy(dp, tblock[trecno], TP_BSIZE); trecno++; *************** *** 35,38 spcl.c_tapea++; ! if(trecno >= ntrec) ! flusht(); } --- 43,46 ----- spcl.c_tapea++; ! if (trecno >= ntrec) ! t_flusht(1, 0); } *************** *** 40,42 dmpblk(blkno, size) ! daddr_t blkno; int size; --- 48,50 ----- dmpblk(blkno, size) ! register daddr_t blkno; int size; *************** *** 43,45 { ! int avail, tpblks, dblkno; --- 51,53 ----- { ! register int avail, tpblks, dblkno; *************** *** 53,55 spcl.c_tapea += avail; ! flusht(); dblkno += avail * (TP_BSIZE / DEV_BSIZE); --- 61,63 ----- spcl.c_tapea += avail; ! t_flusht(1, 0); dblkno += avail * (TP_BSIZE / DEV_BSIZE); *************** *** 61,64 spcl.c_tapea += tpblks; ! if(trecno >= ntrec) ! flusht(); } --- 69,72 ----- spcl.c_tapea += tpblks; ! if (trecno >= ntrec) ! t_flusht(1, 0); } *************** *** 67,69 ! flusht() { --- 75,81 ----- ! /* ! * Write and/or wait for previous writes. ! */ ! t_flusht(dowrite, dowait) ! int dowrite, dowait; { *************** *** 69,71 { ! register i, si; daddr_t d; --- 81,83 ----- { ! register int i, si; daddr_t d; *************** *** 72,73 trecno = 0; --- 84,91 ----- + if (dowait && mass_driver && !pipeout) { + if (wrwait()) + goto tape_err; + } + if (!dowrite) + return; trecno = 0; *************** *** 73,100 trecno = 0; ! if (write(to, tblock[0], writesize) != writesize){ ! if (pipeout) { ! msg("Tape write error on %s\n", tape); ! msg("Cannot recover\n"); ! dumpabort(); ! /* NOTREACHED */ ! } ! msg("Tape write error on tape %d\n", tapeno); ! broadcast("TAPE ERROR!\n"); ! if (query("Do you want to restart?")){ ! msg("This tape will rewind. After it is rewound,\n"); ! msg("replace the faulty tape with a new one;\n"); ! msg("this dump volume will be rewritten.\n"); ! /* ! * Temporarily change the tapeno identification ! */ ! tapeno--; ! nogripe = 1; ! close_rewind(); ! nogripe = 0; ! tapeno++; ! Exit(X_REWRITE); ! } else { ! dumpabort(); ! /*NOTREACHED*/ ! } } --- 91,95 ----- trecno = 0; ! if (mass_driver && !pipeout) { ! if (wrrec(tblock[0])) ! goto tape_err; } *************** *** 100,102 } ! asize += writesize/density; --- 95,100 ----- } ! else { ! if (write(to, tblock[0], writesize) != writesize) ! goto tape_err; ! } asize += writesize/density; *************** *** 109,110 timeest(); } --- 107,138 ----- timeest(); + return; + + tape_err: + if (nogripe) /* already handling an error, continue */ + return; + if (pipeout) { + msg("Tape write error on %s\n", tape); + msg("Cannot recover\n"); + dumpabort(); + /* NOTREACHED */ + } + msg("Tape write error on tape %d\n", tapeno); + broadcast("TAPE ERROR!\n"); + if (query("Do you want to restart?")) { + msg("This tape will rewind. After it is rewound,\n"); + msg("replace the faulty tape with a new one;\n"); + msg("this dump volume will be rewritten.\n"); + /* + * Temporarily change the tapeno identification + */ + tapeno--; + nogripe = 1; + close_rewind(); + nogripe = 0; + tapeno++; + Exit(X_REWRITE); + } + else + dumpabort(); + /*NOTREACHED*/ } *************** *** 111,112 rewind() --- 139,143 ----- + /* + * Rewind the tape + */ rewind() *************** *** 125,126 */ msg("Tape rewinding\n", secs); --- 156,159 ----- */ + if (drivfd >= 0) + t_flusht(0, 1); msg("Tape rewinding\n", secs); *************** *** 126,127 msg("Tape rewinding\n", secs); close(to); --- 159,164 ----- msg("Tape rewinding\n", secs); + if (drivfd >= 0) { + close(drivfd); + drivfd = -1; + } close(to); *************** *** 138,139 return; close(to); --- 175,181 ----- return; + if (drivfd >= 0) { + t_flusht(0, 1); + close(drivfd); + drivfd = -1; + } close(to); *************** *** 139,141 close(to); ! if (!nogripe){ rewind(); --- 181,183 ----- close(to); ! if (!nogripe) { rewind(); *************** *** 144,146 } ! do{ if (query ("Is the new tape mounted and ready to go?")) --- 186,188 ----- } ! for (;;) { if (query ("Is the new tape mounted and ready to go?")) *************** *** 147,149 break; ! if (query ("Do you want to abort?")){ dumpabort(); --- 189,191 ----- break; ! if (query ("Do you want to abort?")) { dumpabort(); *************** *** 151,153 } ! } while (1); } --- 193,195 ----- } ! } } *************** *** 177,178 */ close(to); --- 219,225 ----- */ + if (drivfd >= 0) { + t_flusht(0, 1); + close(drivfd); + drivfd = -1; + } close(to); *************** *** 186,188 childpid = fork(); ! if (childpid < 0){ msg("Context save fork fails in parent %d\n", parentpid); --- 233,235 ----- childpid = fork(); ! if (childpid < 0) { msg("Context save fork fails in parent %d\n", parentpid); *************** *** 190,192 } ! if (childpid != 0){ /* --- 237,239 ----- } ! if (childpid != 0) { /* *************** *** 202,204 #endif TDEBUG ! for (;;){ waitpid = wait(&status); --- 249,251 ----- #endif TDEBUG ! for (;;) { waitpid = wait(&status); *************** *** 204,206 waitpid = wait(&status); ! if (waitpid != childpid){ msg("Parent %d waiting for child %d has another child %d return\n", --- 251,253 ----- waitpid = wait(&status); ! if (waitpid != childpid) { msg("Parent %d waiting for child %d has another child %d return\n", *************** *** 210,212 } ! if (status & 0xFF){ msg("Child %d returns LOB status %o\n", --- 257,259 ----- } ! if (status & 0xFF) { msg("Child %d returns LOB status %o\n", *************** *** 216,218 #ifdef TDEBUG ! switch(status){ case X_FINOK: --- 263,265 ----- #ifdef TDEBUG ! switch (status) { case X_FINOK: *************** *** 231,233 #endif TDEBUG ! switch(status){ case X_FINOK: --- 278,280 ----- #endif TDEBUG ! switch (status) { case X_FINOK: *************** *** 249,251 #endif ! do{ if (pipeout) --- 296,298 ----- #endif ! for (;;) { if (pipeout) *************** *** 254,257 to = creat(tape, 0666); ! if (to < 0) { ! if (!query("Cannot open tape. Do you want to retry the open?")) dumpabort(); --- 301,314 ----- to = creat(tape, 0666); ! if (to >= 0) ! break; ! if (!query("Cannot open tape. Do you want to retry the open?")) { ! dumpabort(); ! /*NOTREACHED*/ ! } ! } ! if (mass_driver && !pipeout) { ! for (;;) { ! if (open_driver(to) == 0) ! break; ! if (!query("Cannot open mass driver. Do you want to retry the open?")) { dumpabort(); *************** *** 257,260 dumpabort(); ! } else break; ! } while (1); --- 314,319 ----- dumpabort(); ! /*NOTREACHED*/ ! } ! } ! } *************** *** 293,294 exit(status); } --- 352,493 ----- exit(status); + } + + /* + * Routines for dealing with the mass driver + */ + + /* + * Wait for all pending I/O to complete, then check the return + * values for each. + */ + wrwait() + { + struct diocret rval; + + while (ioctl(drivfd, DIOCWAIT, 0)) { + if (errno == EINTR) + continue; + perror("ioctl(DIOCWAIT)"); + msg("Bug! DIOCWAIT fails\n"); + return (-1); + } + while (wr_pend > 0) { + if (ioctl(drivfd, DIOCGETRET, &rval) == 0) { + wr_pend--; + if (rval.dioc_error) { + errno = rval.dioc_error; + perror("wrwait"); + return (-1); + } + if (rval.dioc_rval != writesize) + return (-1); + continue; + } + if (errno == EINTR) + continue; + perror("ioctl(DIOCGETRET)"); + return (-1); + } + return (0); + } + + /* + * Write one record, waiting for one previous write to complete + * if necessary. + */ + wrrec(addr) + char *addr; + { + int n, outbits; + struct diocret rval; + struct timeval tv; + + tv.tv_sec = tv.tv_usec = 0; + while (wr_pend > 0) { + outbits = 1 << drivfd; + n = select(drivfd + 1, (int *)0, &outbits, (int *)0, + wr_pend >= wr_maxpend ? (struct timeval *)0 : &tv); + if (n < 0) { + if (errno == EINTR) + continue; + perror("select"); + return (-1); + } + if (n == 0) { + if (wr_pend < wr_maxpend) + break; + msg("Bogus zero return from select\n"); + return (-1); + } + if (ioctl(drivfd, DIOCGETRET, &rval)) { + perror("ioctl(DIOCGETRET)"); + return (-1); + } + wr_pend--; + if (rval.dioc_error) { + errno = rval.dioc_error; + perror("wrrec"); + return (-1); + } + if (rval.dioc_rval != writesize) + return (-1); + } + if (write(drivfd, addr, writesize) != writesize) { + perror("write"); + return (-1); + } + wr_pend++; + return (0); + } + + /* + * Find and open /dev/drivX, and connect it to the tape (to). + * Set wr_maxpend according to the maximum allowable pending operations. + */ + open_driver(to) + int to; + { + int i; + char driv_name[40]; + struct stat st; + struct diocinfo di; + char *sprintf(); + + for (i = 0;; i++) { + (void) sprintf(driv_name, "/dev/driv%d", i); + if ((drivfd = open(driv_name, 2)) >= 0) + break; + if (stat(driv_name, &st)) + return (-1); + } + if (ioctl (drivfd, DIOCGMAXX, &i)) { + perror("ioctl(DIOCGMAXX)"); + goto out; + } + if (i < 3) { + msg("This kernel' driver's max_pend is too small\n"); + goto out; + } + wr_maxpend = i - 2; /* safety margin (?) */ + if (WR_MAX && wr_maxpend > WR_MAX) + wr_maxpend = WR_MAX; + + di.dioc_fd = to; + di.dioc_xsize = writesize; + again: + di.dioc_nxfer = wr_maxpend; + if (ioctl(drivfd, DIOCSETINFO, &di)) { + if (errno == ENOMEM && wr_maxpend > 1) { + wr_maxpend--; + goto again; + } + perror("ioctl(DIOCSETINFO)"); + goto out; + } + msg("[wr_maxpend set to %d]\n", wr_maxpend);/* debug */ + return (0); + + out: + close(drivfd); + return (-1); } RCS file: RCS/dumptraverse.c,v retrieving revision 1.1 diff -c1 -r1.1 dumptraverse.c *** /tmp/,RCSt1005046 Sat Jan 5 03:23:21 1985 --- dumptraverse.c Mon Dec 31 23:06:24 1984 *************** *** 5,8 pass(fn, map) ! int (*fn)(); ! char *map; { --- 5,8 ----- pass(fn, map) ! register int (*fn)(); ! register char *map; { *************** *** 8,12 { ! struct dinode *dp; ! int bits; ! ino_t maxino; --- 8,11 ----- { ! register int bits; ! register ino_t maxino; *************** *** 14,16 for (ino = 0; ino < maxino; ) { ! if((ino % NBBY) == 0) { bits = ~0; --- 13,19 ----- for (ino = 0; ino < maxino; ) { ! #if NBBY == 8 ! if ((ino & 7) == 0) { ! #else ! if ((ino % NBBY) == 0) { ! #endif bits = ~0; *************** *** 16,18 bits = ~0; ! if(map != NULL) bits = *map++; --- 19,21 ----- bits = ~0; ! if (map != NULL) bits = *map++; *************** *** 20,25 ino++; ! if(bits & 1) { ! dp = getino(ino); ! (*fn)(dp); ! } bits >>= 1; --- 23,26 ----- ino++; ! if (bits & 1) ! (*fn)(getino(ino)); bits >>= 1; *************** *** 31,33 { ! register f; --- 32,34 ----- { ! register int f; *************** *** 34,36 f = ip->di_mode & IFMT; ! if(f == 0) return; --- 35,37 ----- f = ip->di_mode & IFMT; ! if (f == 0) return; *************** *** 37,39 BIS(ino, clrmap); ! if(f == IFDIR) BIS(ino, dirmap); --- 38,40 ----- BIS(ino, clrmap); ! if (f == IFDIR) BIS(ino, dirmap); *************** *** 51,53 add(ip) ! register struct dinode *ip; { --- 52,54 ----- add(ip) ! register struct dinode *ip; { *************** *** 56,58 ! if(BIT(ino, nodmap)) return; --- 57,59 ----- ! if (BIT(ino, nodmap)) return; *************** *** 70,72 } ! if(dadded) { nadded++; --- 71,73 ----- } ! if (dadded) { nadded++; *************** *** 77,80 } ! if(nsubdir == 0) ! if(!BIT(ino, nodmap)) BIC(ino, dirmap); --- 78,81 ----- } ! if (nsubdir == 0) ! if (!BIT(ino, nodmap)) BIC(ino, dirmap); *************** *** 86,88 { ! register i; daddr_t idblk[MAXNINDIR]; --- 87,89 ----- { ! register int i; daddr_t idblk[MAXNINDIR]; *************** *** 90,93 bread(fsbtodb(sblock, d), (char *)idblk, sblock->fs_bsize); ! if(n <= 0) { ! for(i=0; i < NINDIR(sblock); i++) { d = idblk[i]; --- 91,94 ----- bread(fsbtodb(sblock, d), (char *)idblk, sblock->fs_bsize); ! if (n <= 0) { ! for (i=0; i < NINDIR(sblock); i++) { d = idblk[i]; *************** *** 93,95 d = idblk[i]; ! if(d != 0) dsrch(d, sblock->fs_bsize, *filesize); --- 94,96 ----- d = idblk[i]; ! if (d != 0) dsrch(d, sblock->fs_bsize, *filesize); *************** *** 99,101 n--; ! for(i=0; i < NINDIR(sblock); i++) { d = idblk[i]; --- 100,102 ----- n--; ! for (i=0; i < NINDIR(sblock); i++) { d = idblk[i]; *************** *** 101,103 d = idblk[i]; ! if(d != 0) indir(d, n, filesize); --- 102,104 ----- d = idblk[i]; ! if (d != 0) indir(d, n, filesize); *************** *** 107,109 ! dump(ip) struct dinode *ip; --- 108,116 ----- ! /* ! * Like dump, but checks for inodes that aren't directories. This is ! * really not right, but prevents restore from believing that this inode ! * entry (which has changed into a file while we were doing other stuff) ! * is the end of the list of directories. ! */ ! dirdump(ip) struct dinode *ip; *************** *** 110,111 { register int i; --- 117,129 ----- { + if ((ip->di_mode & IFMT) != IFDIR) { + msg("WARNING: active file system; directory vanished\n"); + msg("(you aren't supposed to dump active file systems.)\n"); + return; + } + dump(ip); + } + + dump(ip) + register struct dinode *ip; + { register int i; *************** *** 113,115 ! if(newtape) { newtape = 0; --- 131,133 ----- ! if (newtape) { newtape = 0; *************** *** 122,123 i = ip->di_mode & IFMT; if ((i != IFDIR && i != IFREG && i != IFLNK) || ip->di_size == 0) { --- 140,146 ----- i = ip->di_mode & IFMT; + if (i == 0) { /* free inode */ + msg("WARNING: active file system; file vanished\n"); + msg("(you aren't supposed to dump active file systems.)\n"); + return; + } if ((i != IFDIR && i != IFREG && i != IFLNK) || ip->di_size == 0) { *************** *** 171,173 blksout(blkp, frags) ! daddr_t *blkp; int frags; --- 194,196 ----- blksout(blkp, frags) ! register daddr_t *blkp; int frags; *************** *** 174,176 { ! int i, j, count, blks, tbperdb; --- 197,199 ----- { ! register int i, j, count, blks, tbperdb; *************** *** 205,208 { ! register i, n; ! char *cp; --- 228,231 ----- { ! register int i; ! register char *cp; *************** *** 208,216 - n = -1; - for (i = 0; i < msiz; i++) - if(map[i]) - n = i; - if (n < 0) - return; - n++; spcl.c_type = typ; --- 231,232 ----- spcl.c_type = typ; *************** *** 216,218 spcl.c_type = typ; ! spcl.c_count = howmany(n * sizeof(map[0]), TP_BSIZE); spclrec(); --- 232,234 ----- spcl.c_type = typ; ! spcl.c_count = howmany(msiz * sizeof(map[0]), TP_BSIZE); spclrec(); *************** *** 231,233 s = 0; ! for(i = 0; i < sizeof(union u_spcl)/sizeof(int); i++) s += *ip++; --- 247,249 ----- s = 0; ! for (i = 0; i < sizeof(union u_spcl)/sizeof(int); i++) s += *ip++; *************** *** 239,241 daddr_t d; ! int size, filesize; { --- 255,258 ----- daddr_t d; ! int size; ! register int filesize; { *************** *** 242,244 register struct direct *dp; ! long loc; char dblk[MAXBSIZE]; --- 259,261 ----- register struct direct *dp; ! register long loc; char dblk[MAXBSIZE]; *************** *** 245,247 ! if(dadded) return; --- 262,264 ----- ! if (dadded) return; *************** *** 257,259 loc += dp->d_reclen; ! if(dp->d_ino == 0) continue; --- 274,276 ----- loc += dp->d_reclen; ! if (dp->d_ino == 0) continue; *************** *** 259,262 continue; ! if(dp->d_name[0] == '.') { ! if(dp->d_name[1] == '\0') continue; --- 276,279 ----- continue; ! if (dp->d_name[0] == '.') { ! if (dp->d_name[1] == '\0') continue; *************** *** 262,264 continue; ! if(dp->d_name[1] == '.' && dp->d_name[2] == '\0') continue; --- 279,281 ----- continue; ! if (dp->d_name[1] == '.' && dp->d_name[2] == '\0') continue; *************** *** 265,267 } ! if(BIT(dp->d_ino, nodmap)) { dadded++; --- 282,284 ----- } ! if (BIT(dp->d_ino, nodmap)) { dadded++; *************** *** 269,271 } ! if(BIT(dp->d_ino, dirmap)) nsubdir++; --- 286,288 ----- } ! if (BIT(dp->d_ino, dirmap)) nsubdir++; *************** *** 296,298 char *ba; ! int cnt; { --- 313,315 ----- char *ba; ! int cnt; { *************** *** 301,303 loop: ! if (lseek(fi, (long)(da * DEV_BSIZE), 0) < 0){ msg("bread: lseek fails\n"); --- 318,320 ----- loop: ! if (lseek(fi, (long)(da * DEV_BSIZE), 0) < 0) msg("bread: lseek fails\n"); *************** *** 303,305 msg("bread: lseek fails\n"); - } n = read(fi, ba, cnt); --- 320,321 ----- msg("bread: lseek fails\n"); n = read(fi, ba, cnt); *************** *** 311,313 * ! * NB - dump only works in TP_BSIZE blocks, hence * rounds DEV_BSIZE fragments up to TP_BSIZE pieces. --- 327,329 ----- * ! * N.B. - dump only works in TP_BSIZE blocks, hence * rounds DEV_BSIZE fragments up to TP_BSIZE pieces. *************** *** 323,325 disk, da, cnt, n); ! if (++breaderrors > BREADEMAX){ msg("More than %d block read errors from %d\n", --- 339,341 ----- disk, da, cnt, n); ! if (++breaderrors > BREADEMAX) { msg("More than %d block read errors from %d\n", *************** *** 328,330 msg("This is an unrecoverable error.\n"); ! if (!query("Do you want to attempt to continue?")){ dumpabort(); --- 344,346 ----- msg("This is an unrecoverable error.\n"); ! if (!query("Do you want to attempt to continue?")) { dumpabort(); *************** *** 331,333 /*NOTREACHED*/ ! } else breaderrors = 0; --- 347,350 ----- /*NOTREACHED*/ ! } ! else breaderrors = 0; //go.sysin dd * made=TRUE if [ $made = TRUE ]; then /bin/chmod 644 dump_mods /bin/echo -n ' '; /bin/ls -ld dump_mods fi /bin/echo 'Extracting md.4' sed 's/^X//' <<'//go.sysin dd *' >md.4 X.TH DRIV 4L "U of Maryland" X.UC 4 X.SH NAME driv \- ``mass driver'' asynchronous device X.SH SYNOPSIS X.B "pseudo-device driv" X.br or X.br X.B "pseudo-device driv" X.I N X.SH DESCRIPTION \fI/dev/driv0\fP \- \fI/dev/driv\fP\|(N-1) are special files that allow asynchronous raw I/O on other devices. They work by stealing memory from the system buffer pool, reserving it for the user of the pseudo driver for asynchronous transfers. This driver does nothing by itself; it X.I must be used in conjunction with another device. Due to system limitations, it generally operates only with mass storage devices (tapes and disks). X.PP The mass driver is controlled by means of X.I ioctl commands defined in the file X.RI < sys/drivio.h >, as follows: X.PP X.nf X/* $Header: /usr/sys/h/RCS/drivio.h,v 1.1 85/01/02 09:44:05 chris Exp $ */ X/* * diocinfo contains the information needed to initialize the mass driver */ struct diocinfo { int dioc_fd; /* file descriptor */ int dioc_xsize; /* max size of any one transfer */ int dioc_nxfer; /* max number of uncompleted transfers */ }; X/* * diocret contains the return status information for completed transfers */ struct diocret { int dioc_rval; /* return value */ int dioc_error; /* error number */ }; #define DIOCSETINFO _IOW(D, 0, struct diocinfo) /* set info */ #define DIOCREAD _IO(D, 1) /* read (NOT DONE YET) */ #define DIOCGETRET _IOR(D, 2, struct diocret) /* get return info */ #define DIOCWAIT _IO(D, 3) /* wait for I/O to finish */ #define DIOCGMAXX _IOR(D, 4, int) /* get max # xfers */ X.PP X.fi X.PP X.B DIOCSETINFO is used to initialize the mass driver. It connects the mass driver to the file opened as X.IR dioc_fd , which must be a character (raw) device (most likely a tape drive) and must support the mass driver. At the same time, space for holding transfers is allocated based on X.I dioc_xsize and X.IR dioc_nxfer . The first is the maximum size allowed in X.I read or X.I write system calls on the mass driver. (Note that the raw device may be used to perform larger transfers, if necessary.) There is an absolute limit of X.B MAXBSIZE bytes, which can never be exceeded (short of recompiling the kernel). X.RB ( MAXBSIZE may be found in the file X.RI < sys/param.h >). There is also an implementation-dependent limit on the number of transfers X.IR dioc_nxfer ; this can be found X.RI ( before the mass driver is connected) via the X.B DIOCGMAXX ioctl. (Once the driver is successfully connected, X.B DIOCGMAXX will return the value given as X.IR dioc_nxfer .) X.PP Once the mass driver has been successfully connected to the I/O device, asynchronous writes can be initiated with the X.I write system call. When a write occurs, the driver first waits if necessary so that no more than X.I dioc_nxfer asynchronous transfers are still pending, then starts but does not wait for the given transfer. When the X.I write system call returns, the data has been copied someplace safe, so the buffer passed to X.I write may be immediately reused. X.PP X.IR Write s on the mass driver always succeed immediately (assuming they are not too large), moving the mass driver file's seek pointer (but not that of the true device; this is important on devices that use the file offset, e.g., disk drives). Return values are computed, and errors are detected, after the mass driver write has succeeded. These values should be retrieved with the X.B DIOCGETRET ioctl and examined. The X.I select system call will succeed for writing whenever a return value is available (yes, it's odd, but what the heck). The value that X.I would have been returned from a X.I write on the raw device is given back in X.IR dioc_rval , with X.I dioc_error containing the system error number, if any (see X.RI < errno.h >), or zero for no error. (Note that it is possible to have a nonzero return value and an error, if a transfer succeeds partially.) Transfers are always done in order, thus the return value applies to the oldest write for which no value has been returned yet. X.PP The X.B DIOCWAIT command waits for all pending transfers to complete, after which their return values may be obtained. X.PP Currently, X.B DIOCREAD and read transfers are not supported (sorry!). The current idea for these is to have X.B DIOCREAD take a transfer size (and an offset?) and start a transfer, with select for read returning when the read is complete. X.SH ERRORS There are a large number of error codes that can be returned, some probably inappropriate. The following errors can be returned by the mass driver (and are additional to errors from the standard system call interface). X.PP X.TP 15 [ENOENT] A X.B DIOCGETRET ioctl was attempted but there were no return values. X.TP 15 [EBADF] Either of the following: X.br \(bu The X.I dioc_fd given to X.B DIOCSETINFO did not refer to an open file. X.br \(bu A X.I write was attempted when the true device was only opened for reading. X.TP 15 [ENOMEM] Either of the following: X.br \(bu Not enough buffer space was available to allocate X.I dioc_nxfer transfer buffers of size X.IR dioc_xsize . X.br \(bu A X.I write of more than X.I dioc_xsize bytes was attempted. X.TP 15 [EBUSY] The driver is in use by another program. X.TP 15 [EINVAL] Any of the following: X.br \(bu A X.B DIOCSETINFO command was done but the mass driver was already connected. X.br \(bu The X.I dioc_nxfer or X.I dioc_xsize value given to X.B DIOCSETINFO was negative. X.br \(bu The X.I dioc_fd file descriptor did not refer to a character special device, or the device does not support the mass driver. X.br \(bu A X.I write was attempted without connecting the mass driver to a real device. X.TP 15 [ENOTTY] An unsupported ioctl was attempted. X.TP 15 [ENOSPC] The value of X.I dioc_xsize given to X.B DIOCSETINFO was greater than X.BR MAXBSIZE . X.TP 15 [EOPNOTSUPP] A X.I read or X.B DIOCREAD was attempted. This is probably the wrong error number. It may change to ENXIO (or it may go away (wish wish)). X.SH AUTHOR Chris Torek, University of Maryland X.br <chris@maryland.ARPA> X.br <chris@umcp-cs.UUCP> X.SH FILES X/dev/driv* X.SH BUGS Reads should be supported. X.PP Half of the buffer cache is reserved for the normal block I/O system and cannot be used by the mass driver. However, it is still possible for a malicious user to steal half the system buffer space, adversely affecting system performance. (So restrict the /dev entry, silly!) X.PP The method of obtaining return values is ugly. X.PP The effect of select is odd. X.PP While the mass driver is open, the ``true'' (raw) device is held open. The correct procedure for shutting things down is to close the mass driver, then the raw device. Simply closing a raw tape drive will not cause it to rewind, for example. X.PP The error returns are weird. X.PP There should be ioctls to get the current number of pending transfers and valid return values and any other interesting goodies. X.PP Errors are not handled gracefully. If an error occurs on the true device, the mass driver barrels on ahead with the rest of the pending transfers. Probably, it should suspend them, allowing a later ioctl to restart or cancel the pending transfers. X.PP The X.B MAXBSIZE limit is annoying. //go.sysin dd * made=TRUE if [ $made = TRUE ]; then /bin/chmod 644 md.4 /bin/echo -n ' '; /bin/ls -ld md.4 fi /bin/echo 'Extracting needless_conf.h' sed 's/^X//' <<'//go.sysin dd *' >needless_conf.h Here is a PARTIAL list of files that needlessly include ../h/conf.h: sys/kern_descrip.c sys/kern_prot.c sys/kern_sig.c sys/subr_prf.c sys/tty_bk.c sys/tty_subr.c sys/tty_tb.c sys/ufs_alloc.c sys/ufs_bmap.c sys/ufs_fio.c sys/ufs_inode.c sys/ufs_nami.c sys/ufs_subr.c sys/ufs_xxx.c //go.sysin dd * made=TRUE if [ $made = TRUE ]; then /bin/chmod 644 needless_conf.h /bin/echo -n ' '; /bin/ls -ld needless_conf.h fi -- (This line accidently left nonblank.) In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (301) 454-7690 UUCP: {seismo,allegra,brl-bmd}!umcp-cs!chris CSNet: chris@umcp-cs ARPA: chris@maryland
chris@umcp-cs.UUCP (Chris Torek) (01/05/85)
: Run this shell script with "sh" not "csh" PATH=:/bin:/usr/bin:/usr/ucb export PATH all=FALSE if [ $1x = -ax ]; then all=TRUE fi /bin/echo 'Extracting kernel_mods' sed 's/^X//' <<'//go.sysin dd *' >kernel_mods WARNING: You can't just apply these diffs. There are comments next to each to tell you why it's there. Some of them are parts of other fixes, some are local devices; anyway, you have to read the ``comments''. Be sure to read the README first! RCS file: RCS/conf.c,v retrieving revision 1.1 diff -b -c1 -r1.1 conf.c *** /tmp/,RCSt1003142 Fri Jan 4 23:00:18 1985 --- conf.c Thu Jan 3 11:57:30 1985 *************** I think this one is obvious. *** 14,16 int hpopen(),hpstrategy(),hpread(),hpwrite(),hpdump(),hpioctl(),hpsize(); ! #else #define hpopen nodev --- 14,16 ----- int hpopen(),hpstrategy(),hpread(),hpwrite(),hpdump(),hpioctl(),hpsize(); ! #else NHP > 0 #define hpopen nodev *************** Likewise... *** 22,24 #define hpsize 0 ! #endif --- 22,24 ----- #define hpsize 0 ! #endif NHP > 0 *************** Here's an addition for the mass driver on TU77s. *** 27,28 int htopen(),htclose(),htstrategy(),htread(),htwrite(),htdump(),htioctl(); #else --- 27,29 ----- int htopen(),htclose(),htstrategy(),htread(),htwrite(),htdump(),htioctl(); + int htmass(); #else *************** Again, but if you have no TU77s. *** 35,36 #define htioctl nodev #endif --- 36,38 ----- #define htioctl nodev + #define htmass 0 #endif *************** Not sure what this is; something used at BRL. *************** You probably don't want it. *** 37,38 #include "rk.h" --- 39,51 ----- + #include "rf.h" + #if NXF > 0 + int rfopen(),rfstrategy(),rfread(),rfwrite(),rfreset(); + #else + #define rfopen nodev + #define rfstrategy nodev + #define rfread nodev + #define rfwrite nodev + #define rfreset nodev + #endif + #include "rk.h" *************** More mass driver stuff, this for the TS11. *** 70,72 int tsopen(),tsclose(),tsstrategy(),tsread(),tswrite(); ! int tsioctl(),tsdump(),tsreset(); #else --- 83,85 ----- int tsopen(),tsclose(),tsstrategy(),tsread(),tswrite(); ! int tsioctl(),tsdump(),tsreset(),tsmass(); #else *************** Same, but if you have no TS11s. *** 80,81 #define tsreset nodev #endif --- 93,95 ----- #define tsreset nodev + #define tsmass 0 #endif *************** Still more mass driver additions, for the TU78. *** 85,87 int mtopen(),mtclose(),mtstrategy(),mtread(),mtwrite(); ! int mtioctl(),mtdump(); #else --- 99,101 ----- int mtopen(),mtclose(),mtstrategy(),mtread(),mtwrite(); ! int mtioctl(),mtdump(),mtmass(); #else *************** Mass driver stuff for when you have no TU78s. *** 94,95 #define mtdump nodev #endif --- 108,110 ----- #define mtdump nodev + #define mtmass 0 #endif *************** The BRL rf disk, which you probably don't want. *** 231,232 rlsize, 0 }, }; --- 246,249 ----- rlsize, 0 }, + { rfopen, nulldev, rfstrategy, nodev, /*15*/ + 0, 0 }, }; *************** The dh ``outgoing mode'' mods, which I posted before. *************** If you didn't get them then, you don't want this now. *** 263,264 #define dh11 0 #else --- 280,285 ----- #define dh11 0 + #define dhoopen nodev + #define dhoclose nodev + #define dhpopen nodev + #define dhpclose nodev #else *************** Continuation of above... *** 266,267 struct tty dh11[]; #endif --- 287,294 ----- struct tty dh11[]; + #include "dho.h" + #if NDHO > 0 + int dhoopen(),dhoclose(); + #else + #define dhoopen nodev + #define dhoclose nodev #endif *************** Passive mode DH (doesn't quite work anyway; you don't want it) *** 267,268 #endif --- 294,303 ----- #endif + #include "dhp.h" + #if NDHP > 0 + int dhpopen(),dhpclose(); + #else + #define dhpopen nodev + #define dhpclose nodev + #endif + #endif *************** 1. The ``file descriptor'' pseudo-device. If you didn't *************** get a copy earlier, ignore these too. *************** 2. The ``mass driver'' pseudo-device (from #include "driv.h" *************** on. Now this, you want.... *** 268,269 #include "dmf.h" --- 303,324 ----- + #include "fd.h" + #if NFD > 0 + int fdopen(); + #else + #define fdopen nodev + #endif NFD + + #include "driv.h" + #if NDRIV > 0 + int drivopen(), drivclose(), drivread(), drivwrite(), drivioctl(); + int drivselect(); + #else NDRIV > 0 + #define drivopen nodev + #define drivclose nodev + #define drivread nodev + #define drivwrite nodev + #define drivioctl nodev + #define drivselect nodev + #endif NDRIV > 0 + #include "dmf.h" *************** DZ outgoing mods. Ignore these if you haven't got them *************** already... *** 302,303 #define dz_tty 0 #else --- 357,360 ----- #define dz_tty 0 + #define dzoopen nodev + #define dzoclose nodev #else *************** etc... *** 305,306 struct tty dz_tty[]; #endif --- 362,369 ----- struct tty dz_tty[]; + #include "dzo.h" + #if NDZO > 0 + int dzoopen(),dzoclose(); + #else + #define dzoopen nodev + #define dzoclose nodev #endif *************** etc... *** 306,307 #endif --- 369,371 ----- #endif + #endif *************** Another BRL addition, the Ikonas frame buffer. Ignore... *** 411,412 #include "ps.h" --- 475,488 ----- + #include "ik.h" + #if NIK > 0 + int ikopen(),ikclose(),ikread(),ikwrite(),ikioctl(),ikreset(); + #else + #define ikopen nodev + #define ikclose nodev + #define ikread nodev + #define ikwrite nodev + #define ikioctl nodev + #define ikreset nodev + #endif + #include "ps.h" *************** Here come a bunch of BRL and U of MD local devices, *************** which you also don't want. *** 445,446 int ttselect(), seltrue(); --- 521,616 ----- + #include "mg.h" /* BRL */ + #if NMG > 0 + int mgopen(),mgclose(),mgreset(),mgread(),mgwrite(),mgioctl(),mgselect(); + #else + #define mgopen nodev + #define mgclose nodev + #define mgreset nodev + #define mgread nodev + #define mgwrite nodev + #define mgioctl nodev + #define mgselect nodev + #endif + + #include "vg.h" /* BRL */ + #if NVG > 0 + int vgopen(),vgclose(),vgreset(),vgread(),vgwrite(),vgioctl(),vgselect(); + #else + #define vgopen nodev + #define vgclose nodev + #define vgreset nodev + #define vgread nodev + #define vgwrite nodev + #define vgioctl nodev + #define vgselect nodev + #endif + + #include "ump.h" /* BRL */ + #if NUMP > 0 + int umpopen(),umpclose(),umpread(),umpwrite(),umpioctl(),umpselect(); + #else + #define umpopen nodev + #define umpclose nodev + #define umpread nodev + #define umpwrite nodev + #define umpioctl nodev + #define umpselect nodev + #endif + + #include "hsw.h" /* BRL */ + #if NHSW > 0 + int hswopen(),hswclose(),hswread(),hswwrite(),hswselect(); + #else + #define hswopen nodev + #define hswclose nodev + #define hswread nodev + #define hswwrite nodev + #define hswselect nodev + #endif + + #include "lsb.h" /* BRL */ + #if NLSB > 0 + int lsbopen(),lsbclose(),lsbread(),lsbwrite(),lsbreset(); + #else + #define lsbopen nodev + #define lsbclose nodev + #define lsbread nodev + #define lsbwrite nodev + #define lsbreset nodev + #endif + + #include "mcd.h" /* BRL */ + #if NMCD > 0 + int mcdopen(),mcdclose(),mcdread(),mcdwrite(),mcdreset(); + #else + #define mcdopen nodev + #define mcdclose nodev + #define mcdread nodev + #define mcdwrite nodev + #define mcdreset nulldev + #endif + + #include "mss.h" /* BRL */ + #if NMSS > 0 + int mssopen(),mssclose(),mssselect(),mssreset(), mssioctl(); + #else + #define mssopen nodev + #define mssclose nodev + #define mssselect nodev + #define mssreset nodev + #define mssioctl nodev + #endif + + /* zmob pseudo-device multiplexor FLB */ + #include "zm.h" + #if NZM > 0 + int zmopen(), zmclose(), zmread(), zmwrite(), zmioctl(); + #else + #define zmopen nodev + #define zmclose nodev + #define zmread nodev + #define zmwrite nodev + #define zmioctl nodev + #endif + int ttselect(), seltrue(); *************** Here come changes to the cdevsw[] table, as described *************** in the installation instructions. You need to make *************** the addition of ``0, 0,'' to each existing device in *************** your own table (except of course for those devices with *************** mass driver entries). *** 451,453 cnioctl, nulldev, nulldev, &cons, ! ttselect, nodev, dzopen, dzclose, dzread, dzwrite, /*1*/ --- 621,624 ----- cnioctl, nulldev, nulldev, &cons, ! ttselect, nodev, 0, 0, ! dzopen, dzclose, dzread, dzwrite, /*1*/ *************** *** 454,456 dzioctl, dzstop, dzreset, dz_tty, ! ttselect, nodev, syopen, nulldev, syread, sywrite, /*2*/ --- 625,628 ----- dzioctl, dzstop, dzreset, dz_tty, ! ttselect, nodev, 0, 0, ! syopen, nulldev, syread, sywrite, /*2*/ *************** *** 457,459 syioctl, nulldev, nulldev, 0, ! syselect, nodev, nulldev, nulldev, mmread, mmwrite, /*3*/ --- 629,632 ----- syioctl, nulldev, nulldev, 0, ! syselect, nodev, 0, 0, ! nulldev, nulldev, mmread, mmwrite, /*3*/ *************** *** 460,462 nodev, nulldev, nulldev, 0, ! mmselect, nodev, hpopen, nulldev, hpread, hpwrite, /*4*/ --- 633,636 ----- nodev, nulldev, nulldev, 0, ! mmselect, nodev, 0, 0, ! hpopen, nulldev, hpread, hpwrite, /*4*/ *************** *** 463,465 hpioctl, nodev, nulldev, 0, ! seltrue, nodev, htopen, htclose, htread, htwrite, /*5*/ --- 637,640 ----- hpioctl, nodev, nulldev, 0, ! seltrue, nodev, 0, 0, ! htopen, htclose, htread, htwrite, /*5*/ *************** *** 466,468 htioctl, nodev, nulldev, 0, ! seltrue, nodev, vpopen, vpclose, nodev, vpwrite, /*6*/ --- 641,644 ----- htioctl, nodev, nulldev, 0, ! seltrue, nodev, htmass, htstrategy, ! vpopen, vpclose, nodev, vpwrite, /*6*/ *************** *** 469,471 vpioctl, nulldev, vpreset, 0, ! vpselect, nodev, nulldev, nulldev, swread, swwrite, /*7*/ --- 645,648 ----- vpioctl, nulldev, vpreset, 0, ! vpselect, nodev, 0, 0, ! nulldev, nulldev, swread, swwrite, /*7*/ *************** *** 472,474 nodev, nodev, nulldev, 0, ! nodev, nodev, flopen, flclose, flread, flwrite, /*8*/ --- 649,652 ----- nodev, nodev, nulldev, 0, ! nodev, nodev, 0, 0, ! flopen, flclose, flread, flwrite, /*8*/ *************** *** 475,477 nodev, nodev, nulldev, 0, ! seltrue, nodev, udopen, nulldev, udread, udwrite, /*9*/ --- 653,656 ----- nodev, nodev, nulldev, 0, ! seltrue, nodev, 0, 0, ! udopen, nulldev, udread, udwrite, /*9*/ *************** *** 478,480 nodev, nodev, udreset, 0, ! seltrue, nodev, vaopen, vaclose, nodev, vawrite, /*10*/ --- 657,660 ----- nodev, nodev, udreset, 0, ! seltrue, nodev, 0, 0, ! vaopen, vaclose, nodev, vawrite, /*10*/ *************** *** 481,483 vaioctl, nulldev, vareset, 0, ! vaselect, nodev, rkopen, nulldev, rkread, rkwrite, /*11*/ --- 661,664 ----- vaioctl, nulldev, vareset, 0, ! vaselect, nodev, 0, 0, ! rkopen, nulldev, rkread, rkwrite, /*11*/ *************** *** 484,486 nodev, nodev, rkreset, 0, ! seltrue, nodev, dhopen, dhclose, dhread, dhwrite, /*12*/ --- 665,668 ----- nodev, nodev, rkreset, 0, ! seltrue, nodev, 0, 0, ! dhopen, dhclose, dhread, dhwrite, /*12*/ *************** *** 487,489 dhioctl, dhstop, dhreset, dh11, ! ttselect, nodev, upopen, nulldev, upread, upwrite, /*13*/ --- 669,672 ----- dhioctl, dhstop, dhreset, dh11, ! ttselect, nodev, 0, 0, ! upopen, nulldev, upread, upwrite, /*13*/ *************** *** 490,492 nodev, nodev, upreset, 0, ! seltrue, nodev, tmopen, tmclose, tmread, tmwrite, /*14*/ --- 673,676 ----- nodev, nodev, upreset, 0, ! seltrue, nodev, 0, 0, ! tmopen, tmclose, tmread, tmwrite, /*14*/ *************** *** 493,495 tmioctl, nodev, tmreset, 0, ! seltrue, nodev, lpopen, lpclose, nodev, lpwrite, /*15*/ --- 677,680 ----- tmioctl, nodev, tmreset, 0, ! seltrue, nodev, 0, 0, ! lpopen, lpclose, nodev, lpwrite, /*15*/ *************** *** 496,498 nodev, nodev, lpreset, 0, ! seltrue, nodev, tsopen, tsclose, tsread, tswrite, /*16*/ --- 681,684 ----- nodev, nodev, lpreset, 0, ! seltrue, nodev, 0, 0, ! tsopen, tsclose, tsread, tswrite, /*16*/ *************** *** 499,501 tsioctl, nodev, tsreset, 0, ! seltrue, nodev, utopen, utclose, utread, utwrite, /*17*/ --- 685,688 ----- tsioctl, nodev, tsreset, 0, ! seltrue, nodev, tsmass, tsstrategy, ! utopen, utclose, utread, utwrite, /*17*/ *************** *** 502,504 utioctl, nodev, utreset, 0, ! seltrue, nodev, ctopen, ctclose, nodev, ctwrite, /*18*/ --- 689,692 ----- utioctl, nodev, utreset, 0, ! seltrue, nodev, 0, 0, ! ctopen, ctclose, nodev, ctwrite, /*18*/ *************** *** 505,507 nodev, nodev, nulldev, 0, ! seltrue, nodev, mtopen, mtclose, mtread, mtwrite, /*19*/ --- 693,696 ----- nodev, nodev, nulldev, 0, ! seltrue, nodev, 0, 0, ! mtopen, mtclose, mtread, mtwrite, /*19*/ *************** *** 508,510 mtioctl, nodev, nodev, 0, ! seltrue, nodev, ptsopen, ptsclose, ptsread, ptswrite, /*20*/ --- 697,700 ----- mtioctl, nodev, nodev, 0, ! seltrue, nodev, mtmass, mtstrategy, ! ptsopen, ptsclose, ptsread, ptswrite, /*20*/ *************** *** 511,513 ptyioctl, ptsstop, nodev, pt_tty, ! ttselect, nodev, ptcopen, ptcclose, ptcread, ptcwrite, /*21*/ --- 701,704 ----- ptyioctl, ptsstop, nodev, pt_tty, ! ttselect, nodev, 0, 0, ! ptcopen, ptcclose, ptcread, ptcwrite, /*21*/ *************** *** 514,516 ptyioctl, nulldev, nodev, pt_tty, ! ptcselect, nodev, dmfopen, dmfclose, dmfread, dmfwrite, /*22*/ --- 705,708 ----- ptyioctl, nulldev, nodev, pt_tty, ! ptcselect, nodev, 0, 0, ! dmfopen, dmfclose, dmfread, dmfwrite, /*22*/ *************** *** 517,519 dmfioctl, dmfstop, dmfreset, dmf_tty, ! ttselect, nodev, idcopen, nulldev, idcread, idcwrite, /*23*/ --- 709,712 ----- dmfioctl, dmfstop, dmfreset, dmf_tty, ! ttselect, nodev, 0, 0, ! idcopen, nulldev, idcread, idcwrite, /*23*/ *************** *** 520,522 nodev, nodev, idcreset, 0, ! seltrue, nodev, dnopen, dnclose, nodev, dnwrite, /*24*/ --- 713,716 ----- nodev, nodev, idcreset, 0, ! seltrue, nodev, 0, 0, ! dnopen, dnclose, nodev, dnwrite, /*24*/ *************** *** 523,526 nodev, nodev, nodev, 0, ! seltrue, nodev, ! /* 25-29 reserved to local sites */ gpibopen, gpibclose, gpibread, gpibwrite, /*25*/ --- 717,720 ----- nodev, nodev, nodev, 0, ! seltrue, nodev, 0, 0, ! gpibopen, gpibclose, gpibread, gpibwrite, /*25*/ *************** *** 527,529 gpibioctl, nulldev, nodev, 0, ! seltrue, nodev, lpaopen, lpaclose, lparead, lpawrite, /*26*/ --- 721,724 ----- gpibioctl, nulldev, nodev, 0, ! seltrue, nodev, 0, 0, ! lpaopen, lpaclose, lparead, lpawrite, /*26*/ *************** *** 530,532 lpaioctl, nodev, nulldev, 0, ! seltrue, nodev, psopen, psclose, psread, pswrite, /*27*/ --- 725,728 ----- lpaioctl, nodev, nulldev, 0, ! seltrue, nodev, 0, 0, ! psopen, psclose, psread, pswrite, /*27*/ *************** *** 533,535 psioctl, nodev, psreset, 0, ! seltrue, nodev, ibopen, ibclose, ibread, ibwrite, /*28*/ --- 729,732 ----- psioctl, nodev, psreset, 0, ! seltrue, nodev, 0, 0, ! ibopen, ibclose, ibread, ibwrite, /*28*/ *************** *** 536,538 ibioctl, nodev, nodev, 0, ! seltrue, nodev, adopen, adclose, nodev, nodev, /*29*/ --- 733,736 ----- ibioctl, nodev, nodev, 0, ! seltrue, nodev, 0, 0, ! adopen, adclose, nodev, nodev, /*29*/ *************** *** 539,541 adioctl, nodev, adreset, 0, ! seltrue, nodev, rxopen, rxclose, rxread, rxwrite, /*30*/ --- 737,740 ----- adioctl, nodev, adreset, 0, ! seltrue, nodev, 0, 0, ! rxopen, rxclose, rxread, rxwrite, /*30*/ *************** *** 542,544 rxioctl, nodev, rxreset, 0, ! seltrue, nodev, ikopen, ikclose, ikread, ikwrite, /*31*/ --- 741,744 ----- rxioctl, nodev, rxreset, 0, ! seltrue, nodev, 0, 0, ! ikopen, ikclose, ikread, ikwrite, /*31*/ *************** *** 545,548 ikioctl, nodev, ikreset, 0, ! seltrue, nodev, ! rlopen, nodev, rlread, rlwrite, /* 32 */ nodev, nodev, rlreset, 0, --- 745,749 ----- ikioctl, nodev, ikreset, 0, ! seltrue, nodev, 0, 0, ! ! rlopen, nodev, rlread, rlwrite, /*32*/ nodev, nodev, rlreset, 0, *************** Here come lots of additions. The mass driver entry *************** is at the end of these. *** 548,550 nodev, nodev, rlreset, 0, ! seltrue, nodev, }; --- 749,813 ----- nodev, nodev, rlreset, 0, ! seltrue, nodev, 0, 0, ! ! /* BRL additions */ ! ! rfopen, nulldev, rfread, rfwrite, /*33*/ ! nodev, nodev, rfreset, 0, ! seltrue, nodev, 0, 0, ! ! vgopen, vgclose, vgread, vgwrite, /*34*/ ! vgioctl, nodev, vgreset, 0, ! vgselect, nodev, 0, 0, ! ! umpopen, umpclose, umpread, umpwrite, /*35*/ ! umpioctl, nodev, nulldev, 0, ! umpselect, nodev, 0, 0, ! ! hswopen, hswclose, hswread, hswwrite, /*36*/ ! nodev, nodev, nulldev, 0, ! hswselect, nodev, 0, 0, ! ! lsbopen, lsbclose, lsbread, lsbwrite, /*37*/ ! nodev, nodev, lsbreset, 0, ! seltrue, nodev, 0, 0, ! ! mcdopen, mcdclose, mcdread, mcdwrite, /*38*/ ! nodev, nodev, mcdreset, 0, ! seltrue, nodev, 0, 0, ! ! mssopen, mssclose, nodev, nodev, /*39*/ ! mssioctl, nodev, mssreset, 0, ! mssselect, nodev, 0, 0, ! ! mgopen, mgclose, mgread, mgwrite, /*40*/ ! mgioctl, nodev, mgreset, 0, ! mgselect, nodev, 0, 0, ! ! /* U of MD additions */ ! ! dzoopen, dzoclose, dzread, dzwrite, /*41*/ ! dzioctl, dzstop, nulldev, dz_tty, ! ttselect, nodev, 0, 0, ! ! dhoopen, dhoclose, dhread, dhwrite, /*42*/ ! dhioctl, dhstop, nulldev, dh11, ! ttselect, nodev, 0, 0, ! ! dhpopen, dhpclose, dhread, dhwrite, /*43*/ ! dhioctl, dhstop, nulldev, dh11, ! ttselect, nodev, 0, 0, ! ! fdopen, nodev, nodev, nodev, /*44*/ ! nodev, nodev, nodev, 0, ! nodev, nodev, 0, 0, ! ! /* moblet multiplexor device: FLB */ ! zmopen, zmclose, zmread, zmwrite, /*45*/ ! zmioctl, nodev, nulldev, 0, ! seltrue, nodev, 0, 0, ! ! /* mass driver */ ! drivopen, drivclose, drivread, drivwrite, /*46*/ ! drivioctl, nodev, nulldev, 0, ! drivselect, nodev, 0, 0, }; *************** Just a minor format gripe. *** 550,551 }; int nchrdev = sizeof (cdevsw) / sizeof (cdevsw[0]); --- 813,815 ----- }; + int nchrdev = sizeof (cdevsw) / sizeof (cdevsw[0]); RCS file: RCS/conf.h,v retrieving revision 1.1 diff -b -c1 -r1.1 conf.h *** /tmp/,RCSt1003100 Fri Jan 4 22:59:28 1985 --- conf.h Thu Jan 3 11:58:43 1985 *************** Here we have the new entries in character (raw) devices *************** to allow them to be used by the mass driver. *** 39,40 int (*d_mmap)(); }; --- 39,42 ----- int (*d_mmap)(); + int (*d_mass)(); + int (*d_bstrat)(); }; RCS file: RCS/fs.h,v retrieving revision 1.1 diff -b -c1 -r1.1 fs.h *** /tmp/,RCSt1003110 Fri Jan 4 22:59:37 1985 --- fs.h Wed Jan 2 09:50:21 1985 *************** Minor glitch in comments fixed. *** 89,92 * within the bounds dictated by MINBSIZE. ! * Note that super blocks are always of size MAXBSIZE, ! * and that MAXBSIZE must be >= MINBSIZE. */ --- 89,92 ----- * within the bounds dictated by MINBSIZE. ! * Note that super blocks are always of size SBSIZE, ! * and that both SBSIZE and MAXBSIZE must be >= MINBSIZE. */ RCS file: RCS/ht.c,v retrieving revision 1.1 diff -b -c1 -r1.1 ht.c *** /tmp/,RCSt1003196 Fri Jan 4 23:01:37 1985 --- ht.c Wed Jan 2 12:19:05 1985 *************** Don't need conf.h in ht.c. *** 18,20 #include "../h/buf.h" - #include "../h/conf.h" #include "../h/dir.h" --- 18,19 ----- #include "../h/buf.h" #include "../h/dir.h" *************** The BRL "commented sleep" which you don't have and thus *************** can't use... *** 173,175 bp->b_flags |= B_WANTED; ! sleep((caddr_t)bp, PRIBIO); } --- 172,174 ----- bp->b_flags |= B_WANTED; ! csleep((caddr_t)bp, PRIBIO, "TAPE"); } *************** Here comes the real mass driver change (actually, addition): *** 454,455 return (0); } --- 453,469 ----- return (0); + } + + /* + * Start a ``raw block transfer'' from kernel space (via the + * mass driver). + */ + htmass(bp) + register struct buf *bp; + { + register struct tu_softc *sc; + + minphys(bp); + sc = &tu_softc[TUUNIT(bp->b_dev)]; + sc->sc_blkno = bdbtofsb(bp->b_blkno); + sc->sc_nxrec = sc->sc_blkno + 1; } RCS file: RCS/machdep.c,v retrieving revision 1.1 diff -b -c1 -r1.1 machdep.c *** /tmp/,RCSt1003151 Fri Jan 4 23:00:37 1985 --- machdep.c Wed Jan 2 10:38:44 1985 *************** Don't ask me! *** 1,2 ! /* machdep.c 6.2 83/10/02 */ --- 1,2 ----- ! /* machdep.c 6.4 (modified) 84/02/02 */ *************** Rearranging a few parameters. You want these changes.... *** 66,68 register struct pte *pte; - int mapaddr, j; register caddr_t v; --- 66,67 ----- register struct pte *pte; register caddr_t v; *************** *** 68,70 register caddr_t v; ! int maxbufs, base, residual; extern char etext; --- 67,70 ----- register caddr_t v; ! register int mapaddr, j; ! int t, base, residual, spaceleft; extern char etext; *************** This next little bit is for a title which we put in the *************** version file. Since you don't do this, you don't want *************** this particular change. (I'll tell you when to start *************** looking again.) *** 70,71 extern char etext; --- 70,72 ----- extern char etext; + extern char vers_title[]; *************** *** 83,84 */ printf(version); --- 84,92 ----- */ + if (vers_title[0]) { + i = strlen(version) - 1; /* sigh */ + version[i] = 0; + printf("%s (%s)\n", version, vers_title); + version[i] = '\n'; + } + else printf(version); *************** Start looking again. Here we change buffer allocation *************** policies... *** 90,91 * We allocate 1/2 as many swap buffer headers as file i/o buffers. */ --- 98,101 ----- * We allocate 1/2 as many swap buffer headers as file i/o buffers. + * MAXBSIZE is probably way bigger than most of the buffers + * we'll need, so we assume buffers of "average" size AVGBSIZE. */ *************** *** 91,94 */ - maxbufs = ((SYSPTSIZE * NBPG) - (5 * (int)(&etext - 0x80000000))) / - MAXBSIZE; if (bufpages == 0) --- 101,102 ----- */ if (bufpages == 0) *************** *** 96,98 if (nbuf == 0) { ! nbuf = bufpages / 2; if (nbuf < 16) --- 104,118 ----- if (nbuf == 0) { ! nbuf = bufpages * CLBYTES / AVGBSIZE; ! /* ! * We need enough space to map everything, so we assume ! * about 700K has to be left after mapping the buffers. ! * (It takes only 6K of pte's to map this, so if we need ! * less, we haven't wasted much memory.) ! */ ! t = ((SYSPTSIZE * NBPG) - 786432) / MAXBSIZE; ! if (nbuf > t) { ! printf("sys pt too small; want %d buffers", nbuf); ! nbuf = t; ! printf(" but space for only %d\n", nbuf); ! } if (nbuf < 16) *************** *** 99,102 nbuf = 16; - if (nbuf > maxbufs) - nbuf = maxbufs; } --- 119,120 ----- nbuf = 16; } *************** *** 102,105 } ! if (bufpages > nbuf * (MAXBSIZE / CLBYTES)) ! bufpages = nbuf * (MAXBSIZE / CLBYTES); if (nswbuf == 0) { --- 120,123 ----- } ! if (bufpages > (nbuf * AVGBSIZE) / CLBYTES) ! bufpages = (nbuf * AVGBSIZE) / CLBYTES; if (nswbuf == 0) { *************** *** 125,126 (name) = (type *)(v); (v) = (caddr_t)((lim) = ((name)+(num))) valloc(buffers, char, MAXBSIZE * nbuf); --- 143,152 ----- (name) = (type *)(v); (v) = (caddr_t)((lim) = ((name)+(num))) + /* + * Map the buffers first, because they are only partially mapped + * (that is to say, they get less physical memory than virtual). + * Each buffer maps a full MAXBSIZE bytes but (at least initially) + * contains only 1/nbuf'th of the total buffer pool, with the + * "extra" pages (if any) given to the first bufpages%nbuf buffers. + * binit() (in ../sys/init_main.c) uses this same convention. + */ valloc(buffers, char, MAXBSIZE * nbuf); *************** *** 128,131 residual = bufpages % nbuf; ! for (i = 0; i < residual; i++) { ! for (j = 0; j < (base + 1) * CLSIZE; j++) { *(int *)(&Sysmap[mapaddr+j]) = PG_V | PG_KW | firstaddr; --- 154,162 ----- residual = bufpages % nbuf; ! for (i = 0; i < nbuf; i++) { ! if (i < residual) ! t = base + 1; ! else ! t = base; ! t *= CLSIZE; ! for (j = 0; j < t; j++) { *(int *)(&Sysmap[mapaddr+j]) = PG_V | PG_KW | firstaddr; *************** *** 136,145 } ! for (i = residual; i < nbuf; i++) { ! for (j = 0; j < base * CLSIZE; j++) { ! *(int *)(&Sysmap[mapaddr+j]) = PG_V | PG_KW | firstaddr; ! clearseg((unsigned)firstaddr); ! firstaddr++; ! } ! mapaddr += MAXBSIZE / NBPG; ! } valloc(buf, struct buf, nbuf); --- 167,171 ----- } ! /* ! * Everything from here on is fully mapped. ! */ valloc(buf, struct buf, nbuf); *************** *** 161,163 /* ! * Now allocate space for core map * Allow space for all of phsical memory minus the amount --- 187,189 ----- /* ! * Now allocate space for core map. * Allow space for all of phsical memory minus the amount *************** *** 163,168 * Allow space for all of phsical memory minus the amount ! * dedicated to the system. The amount of physical memory ! * dedicated to the system is the total virtual memory of ! * the system minus the space in the buffers which is not ! * allocated real memory. */ --- 189,207 ----- * Allow space for all of phsical memory minus the amount ! * dedicated to the system ("kernel memory"). The amount ! * of kernel memory is equal to v-0x80000000 minus the ! * holes in the buffers. In other words: ! * ! * kernel mem = mem used - mem not REALLY used ! * = (v&~0x80000000) - (nbuf*MAXBSIZE-bufpages*CLBYTES) ! * space left = total space - kernel space ! * = physmem*NBPG - kernel space ! * ! * (Of course, when we allocate the core map, we use up some of ! * that left-over space, thus the formula for ncmap below.) ! * There is, however, no guarantee that we have enough pte's ! * to map everything. Here we calculate the ideal size for the ! * core map, find out how much space is left in the system page ! * table, and allocate the minimum of the two numbers. (It ! * currently takes about 100K to map 6M [with CLSIZE == 2 and ! * sizeof (struct cmap) == 16]). */ *************** *** 168,174 */ ! ncmap = (physmem*NBPG - ((int)v &~ 0x80000000) + ! (nbuf * (MAXBSIZE - 2 * CLBYTES))) / ! (NBPG*CLSIZE + sizeof (struct cmap)); ! valloclim(cmap, struct cmap, ncmap, ecmap); ! if ((((int)(ecmap+1))&~0x80000000) > SYSPTSIZE*NBPG) panic("sys pt too small"); --- 207,218 ----- */ ! spaceleft = physmem*NBPG - ((int)v & ~0x80000000) + ! nbuf*MAXBSIZE - bufpages*CLBYTES; ! if (spaceleft < 0) { ! printf("Kernel wants %d more bytes than exist!\n", ! -spaceleft); ! panic("kernel size"); ! } ! ncmap = spaceleft / (CLBYTES + sizeof (struct cmap)); ! spaceleft = SYSPTSIZE*NBPG - (((int)(v + 1)) & ~0x80000000); ! if (spaceleft < 0) panic("sys pt too small"); *************** *** 174,176 panic("sys pt too small"); ! /* --- 218,228 ----- panic("sys pt too small"); ! if (ncmap * sizeof (struct cmap) > spaceleft) { ! printf("sys pt too small; trimmed core map\n"); ! ncmap = spaceleft / sizeof (struct cmap); ! } ! valloclim(cmap, struct cmap, ncmap, ecmap); ! /* anti-bug test: */ ! spaceleft = SYSPTSIZE*NBPG - (((int)(ecmap+1))&~0x80000000); ! if (spaceleft < 0) ! panic("startup"); /* *************** (The part about #if GYRE is for our kernel hack machine.) *** 176,177 /* * Clear allocated space, and make r/w entries --- 228,242 ----- /* + * If there's "lots" of wasted space, gripe. + * (Lots == at least 5% of physical memory in wasted page tables. + * Spaceleft is currently the amount of memory we can still map.) + */ + spaceleft /= NBPG * NPTEPG; /* convert to true pages */ + #if GYRE + if (spaceleft >= NBPG) + printf("%d extra pages in sys pt\n", spaceleft / NBPG); + #else + if (spaceleft >= physmem / 20) + printf("%d extra pages in sys pt\n", spaceleft / NBPG); + #endif + /* * Clear allocated space, and make r/w entries *************** This is part of one of RWS@MIT-BOLD's fixes. I don't know *************** if it would hurt to put it in if you haven't already... it's *************** up to you. *** 286,288 */ ! if (!oonstack && (int)fp <= USRSTACK - ctob(u.u_ssize)) grow((unsigned)fp); --- 351,353 ----- */ ! if ((int)fp <= USRSTACK - ctob(u.u_ssize)) grow((unsigned)fp); *************** I thought this deserved a comment. *** 288,290 grow((unsigned)fp); ! ; #ifndef lint --- 353,355 ----- grow((unsigned)fp); ! ; /* Avoid asm() label botch */ #ifndef lint *************** More of those fixes from RWS@MIT-BOLD. *** 296,298 #endif ! if (!u.u_onstack && (int)scp <= USRSTACK - ctob(u.u_ssize)) grow((unsigned)scp); --- 361,363 ----- #endif ! if ((int)scp <= USRSTACK - ctob(u.u_ssize)) grow((unsigned)scp); *************** (Need I say anything?) *** 360,361 return; #ifndef lint --- 425,427 ----- return; + ; /* Avoid asm() label botch */ #ifndef lint *************** Part of the changes to handle 64K chip controllers. This *************** is not everything you need, so don't install it. *** 426,428 mcr = mcraddr[m]; ! switch (cpu) { #if VAX780 --- 492,494 ----- mcr = mcraddr[m]; ! switch (mcrtype[m]) { #if VAX780 *************** *** 428,431 #if VAX780 ! case VAX_780: ! M780_ENA(mcr); break; --- 494,497 ----- #if VAX780 ! case M780C: ! M780C_ENA(mcr); break; *************** *** 431,432 break; #endif --- 497,504 ----- break; + case M780EL: + M780EL_ENA(mcr); + break; + case M780EU: + M780EU_ENA(mcr); + break; #endif *************** *** 433,435 #if VAX750 ! case VAX_750: M750_ENA(mcr); --- 505,507 ----- #if VAX750 ! case M750: M750_ENA(mcr); *************** *** 438,440 #if VAX730 ! case VAX_730: M730_ENA(mcr); --- 510,512 ----- #if VAX730 ! case M730: M730_ENA(mcr); *************** *** 461,463 mcr = mcraddr[m]; ! switch (cpu) { #if VAX780 --- 533,535 ----- mcr = mcraddr[m]; ! switch (mcrtype[m]) { #if VAX780 *************** *** 463,466 #if VAX780 ! case VAX_780: ! if (M780_ERR(mcr)) { printf("mcr%d: soft ecc addr %x syn %x\n", --- 535,538 ----- #if VAX780 ! case M780C: ! if (M780C_ERR(mcr)) { printf("mcr%d: soft ecc addr %x syn %x\n", *************** *** 466,468 printf("mcr%d: soft ecc addr %x syn %x\n", ! m, M780_ADDR(mcr), M780_SYN(mcr)); #ifdef TRENDATA --- 538,540 ----- printf("mcr%d: soft ecc addr %x syn %x\n", ! m, M780C_ADDR(mcr), M780C_SYN(mcr)); #ifdef TRENDATA *************** *** 470,472 #endif ! M780_INH(mcr); } --- 542,544 ----- #endif ! M780C_INH(mcr); } *************** *** 473,474 break; #endif --- 545,562 ----- break; + + case M780EL: + if (M780EL_ERR(mcr)) { + printf("mcr%d: soft ecc addr %x syn %x\n", + m, M780EL_ADDR(mcr), M780EL_SYN(mcr)); + M780EL_INH(mcr); + } + break; + + case M780EU: + if (M780EU_ERR(mcr)) { + printf("mcr%d: soft ecc addr %x syn %x\n", + m, M780EU_ADDR(mcr), M780EU_SYN(mcr)); + M780EU_INH(mcr); + } + break; #endif *************** *** 475,477 #if VAX750 ! case VAX_750: if (M750_ERR(mcr)) { --- 563,565 ----- #if VAX750 ! case M750: if (M750_ERR(mcr)) { *************** *** 486,488 #if VAX730 ! case VAX_730: { register int mcreg = mcr->mc_reg[1]; --- 574,576 ----- #if VAX730 ! case M730: { register int mcreg = mcr->mc_reg[1]; *************** *** 539,541 ! switch (cpu) { --- 627,629 ----- ! switch (mcrtype[m]) { *************** *** 542,544 #if VAX780 ! case VAX_780: for (i = 0; i < (sizeof (memlogtab) / sizeof (memlogtab[0])); i++) --- 630,632 ----- #if VAX780 ! case M780C: for (i = 0; i < (sizeof (memlogtab) / sizeof (memlogtab[0])); i++) *************** *** 544,546 for (i = 0; i < (sizeof (memlogtab) / sizeof (memlogtab[0])); i++) ! if ((u_char)(M780_SYN(mcr)) == memlogtab[i].m_syndrome) { printf ( --- 632,634 ----- for (i = 0; i < (sizeof (memlogtab) / sizeof (memlogtab[0])); i++) ! if ((u_char)(M780C_SYN(mcr)) == memlogtab[i].m_syndrome) { printf ( *************** *** 549,552 memlogtab[i].m_chip, ! (M780_ADDR(mcr) & 0x8000) ? "upper" : "lower", ! (M780_ADDR(mcr) >> 16)); return; --- 637,640 ----- memlogtab[i].m_chip, ! (M780C_ADDR(mcr) & 0x8000) ? "upper" : "lower", ! (M780C_ADDR(mcr) >> 16)); return; *************** Here come some irrelevant but perhaps useful changes *************** in the panic/reboot code. *** 583,584 boot(paniced, arghowto) --- 671,675 ----- + /* + * Reboot. + */ boot(paniced, arghowto) *************** *** 588,589 register int devtype; /* r10 == major of root dev */ --- 679,682 ----- register int devtype; /* r10 == major of root dev */ + register struct buf *bp; + register iter, nbusy; *************** *** 593,595 #endif ! (void) spl1(); howto = arghowto; --- 686,692 ----- #endif ! /* ! * Figure out whether we can and should complete sandbagged I/O; ! * if so, wait for no busy buffers or a maximum time of ~1 sec. ! */ ! mtpr(IPL, 0x1f); /* block EVERYTHING */ howto = arghowto; *************** *** 597,598 waittime = 0; update(); --- 694,696 ----- waittime = 0; + (void) spl1(); update(); *************** *** 599,607 printf("syncing disks... "); ! #ifdef notdef ! DELAY(10000000); ! #else ! { register struct buf *bp; ! int iter, nbusy; ! ! for (iter = 0; iter < 20; iter++) { nbusy = 0; --- 697,699 ----- printf("syncing disks... "); ! for (iter = 0; iter < 32; iter++) { nbusy = 0; *************** *** 613,614 printf("%d ", nbusy); } --- 705,707 ----- printf("%d ", nbusy); + DELAY(20000); } *************** *** 614,617 } ! } ! #endif printf("done\n"); --- 707,710 ----- } ! if (nbusy != 0) ! printf("%d bufs un", nbusy); printf("done\n"); *************** *** 617,618 printf("done\n"); } --- 710,712 ----- printf("done\n"); + mtpr(IPL, 0x1f); } *************** *** 618,620 } - splx(0x1f); /* extreme priority */ devtype = major(rootdev); --- 712,713 ----- } devtype = major(rootdev); *************** *** 625,627 ; ! } else { if (paniced == RB_PANIC) { --- 718,721 ----- ; ! } ! else { if (paniced == RB_PANIC) { *************** *** 627,629 if (paniced == RB_PANIC) { ! doadump(); /* TXDB_BOOT's itsself */ /*NOTREACHED*/ --- 721,723 ----- if (paniced == RB_PANIC) { ! doadump(); /* TXDB_BOOT's itself */ /*NOTREACHED*/ *************** *** 633,636 #if defined(VAX750) || defined(VAX730) ! if (cpu != VAX_780) ! { asm("movl r11,r5"); } /* boot flags go in r5 */ #endif --- 727,733 ----- #if defined(VAX750) || defined(VAX730) ! /* ! * 750s and 730s want their boot flags in r5 (rather than r11). ! * Doesn't hurt 780s, so just do it all the time. ! */ ! asm("movl r11,r5"); #endif *************** *** 636,638 #endif ! for (;;) asm("halt"); --- 733,735 ----- #endif ! for (;;) { asm("halt"); *************** *** 638,639 asm("halt"); /*NOTREACHED*/ --- 735,737 ----- asm("halt"); + } /*NOTREACHED*/ *************** (Part of?) wls@astrovax's fix for tbuf parity errors. *************** If you haven't installed this, do so, maybe it will *************** help a bit. *** 809,811 mtpr(MCESR, 0xf); ! if ((mcf->mc5_mcesr&0xf) == MC750_TBPAR) { printf("tbuf par: flushing and returning\n"); --- 907,909 ----- mtpr(MCESR, 0xf); ! if ((mcf->mc5_mcesr&0xe) == MC750_TBPAR) { printf("tbuf par: flushing and returning\n"); *************** More BRL csleep changes that you should ignore *** 860,862 while ((bp->b_flags & B_DONE) == 0) ! sleep((caddr_t)bp, prio); splx(s); --- 958,960 ----- while ((bp->b_flags & B_DONE) == 0) ! csleep((caddr_t)bp, prio, "PHYSIO"); splx(s); *************** *** 863 } --- 961,962 ----- } + RCS file: RCS/mba.c,v retrieving revision 1.1 diff -b -c1 -r1.1 mba.c *** /tmp/,RCSt1003207 Fri Jan 4 23:01:50 1985 --- mba.c Fri Jan 4 19:34:40 1985 *************** Another useless "conf.h"! *** 13,15 #include "../h/buf.h" - #include "../h/conf.h" #include "../h/dir.h" --- 13,14 ----- #include "../h/buf.h" #include "../h/dir.h" *************** Track the b_active flag better. (Part of the mass driver *************** changes.) Just about everything else in this file is more *************** of the same. *** 46,48 bp = mi->mi_tab.b_actf; ! if (bp == NULL) return; --- 45,48 ----- bp = mi->mi_tab.b_actf; ! if (bp == NULL) { ! mi->mi_tab.b_active = 0; return; *************** *** 48,49 return; /* --- 48,51 ----- return; + } + mi->mi_tab.b_active = 1; /* *************** *** 56,58 mi->mi_tab.b_actf = bp->av_forw; - mi->mi_tab.b_active = 0; mi->mi_tab.b_errcnt = 0; --- 58,59 ----- mi->mi_tab.b_actf = bp->av_forw; mi->mi_tab.b_errcnt = 0; *************** *** 69,71 case MBU_NEXT: /* request is complete (e.g. ``sense'') */ - mi->mi_tab.b_active = 0; mi->mi_tab.b_errcnt = 0; --- 70,71 ----- case MBU_NEXT: /* request is complete (e.g. ``sense'') */ mi->mi_tab.b_errcnt = 0; *************** *** 91,93 * In any case the device is ``active'' waiting for the ! * data to transfer. */ --- 91,93 ----- * In any case the device is ``active'' waiting for the ! * data to transfer. (mi->mi_tab.b_active was set earlier.) */ *************** *** 93,95 */ - mi->mi_tab.b_active = 1; if (mhp->mh_active == 0) --- 93,94 ----- */ if (mhp->mh_active == 0) *************** *** 107,109 } - mi->mi_tab.b_active = 1; return; --- 106,107 ----- } return; *************** *** 116,117 mi->mi_tab.b_flags |= B_BUSY; return; --- 114,116 ----- mi->mi_tab.b_flags |= B_BUSY; + mi->mi_tab.b_active = 0; /* ??? */ return; *************** *** 143,144 if ((mi = mhp->mh_actf) == NULL) { return; --- 142,144 ----- if ((mi = mhp->mh_actf) == NULL) { + mhp->mh_active = 0; return; *************** *** 146,147 if ((bp = mi->mi_tab.b_actf) == NULL) { mhp->mh_actf = mi->mi_forw; --- 146,148 ----- if ((bp = mi->mi_tab.b_actf) == NULL) { + mi->mi_tab.b_active = 0; mhp->mh_actf = mi->mi_forw; *************** *** 149,150 } /* --- 150,153 ----- } + + mhp->mh_active = 1; /* *************** *** 167,169 mi->mi_tab.b_errcnt = 0; - mi->mi_tab.b_active = 0; bp->b_flags |= B_ERROR; --- 170,171 ----- mi->mi_tab.b_errcnt = 0; bp->b_flags |= B_ERROR; *************** *** 173,178 /* ! * We can do the operation; mark the massbus active ! * and let the device start routine setup any necessary ! * device state for the transfer (e.g. desired cylinder, etc ! * on disks). */ --- 175,179 ----- /* ! * We can do the operation; let the device start routine ! * set up any necessary device state for the transfer ! * (e.g. desired cylinder, etc on disks). */ *************** *** 178,180 */ - mhp->mh_active = 1; if (mi->mi_driver->md_start) { --- 179,180 ----- */ if (mi->mi_driver->md_start) { *************** Part of this is a fix from thomas@utah-gr which you should *************** install anyway, whether or not you are installing the mass *************** driver. (In other words, keep going.) *** 238,239 * are now finished. */ --- 238,242 ----- * are now finished. + * Data transfer complete interrupts do not set the attn + * bit, and positioning commands (e.g. recal) do not set + * DTCMP. */ *************** *** 239,241 */ ! if (mhp->mh_active) { /* --- 242,245 ----- */ ! mi = mhp->mh_actf; ! if (mhp->mh_active && (mbasr&MBSR_DTCMP || as&(1<<mi->mi_drive))) { /* *************** *** 246,248 */ - mi = mhp->mh_actf; as &= ~(1 << mi->mi_drive); --- 250,251 ----- */ as &= ~(1 << mi->mi_drive); *************** *** 324,326 case MBN_DONE: /* operation completed */ - mi->mi_tab.b_active = 0; mi->mi_tab.b_errcnt = 0; --- 327,328 ----- case MBN_DONE: /* operation completed */ mi->mi_tab.b_errcnt = 0; *************** *** 329,330 iodone(bp); /* fall into common code */ --- 331,333 ----- iodone(bp); + mi->mi_tab.b_active = 0; /* fall into common code */ *************** Here's some stuff I did 'cause I thought the code could *************** be cleaned up some. Well, it *is* *slightly* shorter.... *************** (This isn't necessary but can't hurt [famous last words]). *** 383,385 /* ! * Setup the mapping registers for a transfer. */ --- 386,389 ----- /* ! * Set up the mapping registers for a transfer. ! * Leave a zero entry at the end to guard against wild transfers. */ *************** *** 388,396 { ! register struct mba_regs *mbap = mi->mi_mba; ! struct buf *bp = mi->mi_tab.b_actf; ! register int npf; ! unsigned v; ! register struct pte *pte, *io; ! int o; ! struct proc *rp; --- 392,396 ----- { ! register struct buf *bp = mi->mi_tab.b_actf; ! register struct pte *pte; ! register int o; *************** *** 396,398 - v = btop(bp->b_un.b_addr); o = (int)bp->b_un.b_addr & PGOFSET; --- 396,397 ----- o = (int)bp->b_un.b_addr & PGOFSET; *************** *** 398,401 o = (int)bp->b_un.b_addr & PGOFSET; - npf = btoc(bp->b_bcount + o); - rp = bp->b_flags&B_DIRTY ? &proc[2] : bp->b_proc; if ((bp->b_flags & B_PHYS) == 0) --- 397,398 ----- o = (int)bp->b_un.b_addr & PGOFSET; if ((bp->b_flags & B_PHYS) == 0) *************** *** 401,404 if ((bp->b_flags & B_PHYS) == 0) ! pte = &Sysmap[btop(((int)bp->b_un.b_addr)&0x7fffffff)]; ! else if (bp->b_flags & B_UAREA) pte = &rp->p_addr[v]; --- 398,406 ----- if ((bp->b_flags & B_PHYS) == 0) ! pte = &Sysmap[btop((int)bp->b_un.b_addr & 0x7fffffff)]; ! else { ! register struct proc *rp; ! register unsigned v = btop(bp->b_un.b_addr); ! ! rp = bp->b_flags&B_DIRTY ? &proc[2] : bp->b_proc; ! if (bp->b_flags & B_UAREA) pte = &rp->p_addr[v]; *************** *** 408,410 pte = vtopte(rp, v); ! io = mbap->mba_map; while (--npf >= 0) { --- 410,416 ----- pte = vtopte(rp, v); ! } ! { ! register struct pte *io = mi->mi_mba->mba_map; ! register int npf = btoc(bp->b_bcount + o); ! while (--npf >= 0) { *************** *** 411,413 if (pte->pg_pfnum == 0) ! panic("mba, zero entry"); *(int *)io++ = pte++->pg_pfnum | PG_V; --- 417,419 ----- if (pte->pg_pfnum == 0) ! panic("mba zero entry"); *(int *)io++ = pte++->pg_pfnum | PG_V; *************** *** 414,416 } ! *(int *)io++ = 0; return (o); --- 420,423 ----- } ! *(int *)io = 0; ! } return (o); RCS file: RCS/mt.c,v retrieving revision 1.1 diff -b -c1 -r1.1 mt.c *** /tmp/,RCSt1003216 Fri Jan 4 23:02:04 1985 --- mt.c Wed Jan 2 12:22:07 1985 *************** Lots of these changes are stuff I never heard of. The *************** only mass driver change is the addition of mtmass(). *************** You can install these or not, as you choose. *** 9,10 * * TODO: --- 9,15 ----- * + * Changed by Jules P. Aronson to correct + * faulty identification of logical unit numbers with slave numbers + * specifically, the construct MUUNIT(dev) is replaced with sc->sc_slave + * in most cases. + * * TODO: *************** *** 19,21 #include "../h/buf.h" - #include "../h/conf.h" #include "../h/dir.h" --- 24,25 ----- #include "../h/buf.h" #include "../h/dir.h" *************** *** 23,24 #include "../h/user.h" #include "../h/map.h" --- 27,29 ----- #include "../h/user.h" + #include "../h/proc.h" #include "../h/map.h" *************** *** 53,54 #define MTUNIT(dev) (mutomt[MUUNIT(dev)]) --- 58,60 ----- #define MTUNIT(dev) (mutomt[MUUNIT(dev)]) + #define MUSLAVE(dev) ((&mu_softc[MUUNIT(dev)])->sc_slave) *************** *** 68,69 } mu_softc[NMU]; short mutomt[NMU]; --- 74,76 ----- } mu_softc[NMU]; + short mutomt[NMU]; *************** *** 119,122 muunit = MUUNIT(dev); ! if (muunit >= NMU || (sc = &mu_softc[muunit])->sc_openf || ! (mi = mtinfo[MTUNIT(dev)]) == 0 || mi->mi_alive == 0) return (ENXIO); --- 126,128 ----- muunit = MUUNIT(dev); ! if (muunit >= NMU || (mi = mtinfo[MTUNIT(dev)]) == 0 || !mi->mi_alive) return (ENXIO); *************** *** 122,123 return (ENXIO); olddens = sc->sc_dens; --- 128,132 ----- return (ENXIO); + sc = &mu_softc[muunit]; + if (sc->sc_openf) + return (EBUSY); olddens = sc->sc_dens; *************** *** 239,241 } else { ! mtaddr->mtncs[MUUNIT(bp->b_dev)] = (bp->b_repcnt<<8)|bp->b_command|MT_GO; --- 248,250 ----- } else { ! mtaddr->mtncs[sc->sc_slave] = (bp->b_repcnt<<8)|bp->b_command|MT_GO; *************** *** 245,247 if (mi->mi_tab.b_errcnt == 2) { ! mtaddr->mtca = MUUNIT(bp->b_dev); } else { --- 254,256 ----- if (mi->mi_tab.b_errcnt == 2) { ! mtaddr->mtca = sc->sc_slave; } else { *************** *** 248,250 mtaddr->mtbc = bp->b_bcount; ! mtaddr->mtca = (1<<2)|MUUNIT(bp->b_dev); } --- 257,259 ----- mtaddr->mtbc = bp->b_bcount; ! mtaddr->mtca = (1<<2)|sc->sc_slave; } *************** *** 253,255 if (blkno < bdbtofsb(bp->b_blkno)) ! mtaddr->mtncs[MUUNIT(bp->b_dev)] = (min((unsigned)(bdbtofsb(bp->b_blkno) - blkno), 0377) << 8) | --- 262,264 ----- if (blkno < bdbtofsb(bp->b_blkno)) ! mtaddr->mtncs[sc->sc_slave] = (min((unsigned)(bdbtofsb(bp->b_blkno) - blkno), 0377) << 8) | *************** *** 257,259 else ! mtaddr->mtncs[MUUNIT(bp->b_dev)] = (min((unsigned)(blkno - bdbtofsb(bp->b_blkno)), 0377) << 8) | --- 266,268 ----- else ! mtaddr->mtncs[sc->sc_slave] = (min((unsigned)(blkno - bdbtofsb(bp->b_blkno)), 0377) << 8) | *************** *** 284,286 register struct buf *bp = mi->mi_tab.b_actf; ! register struct mu_softc *sc; --- 293,295 ----- register struct buf *bp = mi->mi_tab.b_actf; ! register struct mu_softc *sc = &mu_softc[MUUNIT(bp->b_dev)]; *************** *** 287,289 /* I'M NOT SURE IF THIS SHOULD ALWAYS BE THE CASE SO FOR NOW... */ ! if ((mtaddr->mtca&3) != MUUNIT(bp->b_dev)) { printf("mt: wrong unit!\n"); --- 296,298 ----- /* I'M NOT SURE IF THIS SHOULD ALWAYS BE THE CASE SO FOR NOW... */ ! if ((mtaddr->mtca&3) != sc->sc_slave) { printf("mt: wrong unit!\n"); *************** *** 289,291 printf("mt: wrong unit!\n"); ! mtaddr->mtca = MUUNIT(bp->b_dev); } --- 298,300 ----- printf("mt: wrong unit!\n"); ! mtaddr->mtca = sc->sc_slave; } *************** *** 291,293 } - sc = &mu_softc[MUUNIT(bp->b_dev)]; sc->sc_erreg = mtaddr->mter; --- 300,301 ----- } sc->sc_erreg = mtaddr->mter; *************** *** 369,371 register struct mu_softc *sc; ! int er, fc, unit; --- 377,379 ----- register struct mu_softc *sc; ! int er, fc, slave; *************** *** 371,373 ! unit = (mtaddr->mtner >> 8) & 3; er = MASKREG(mtaddr->mtner); --- 379,381 ----- ! slave = (mtaddr->mtner >> 8) & 3; er = MASKREG(mtaddr->mtner); *************** *** 374,376 /* WILL THIS OCCUR IF ANOTHER DRIVE COMES ONLINE? */ ! if (bp == 0 || unit != MUUNIT(bp->b_dev)) { /* consistency check */ if ((er & MTER_INTCODE) != MTER_ONLINE) --- 382,387 ----- /* WILL THIS OCCUR IF ANOTHER DRIVE COMES ONLINE? */ ! if (bp == NULL) ! return (MBN_SKIP); ! sc = &mu_softc[MUUNIT(bp->b_dev)]; ! if (slave != sc->sc_slave) { /* consistency check */ if ((er & MTER_INTCODE) != MTER_ONLINE) *************** *** 376,378 if ((er & MTER_INTCODE) != MTER_ONLINE) ! printf("mt: unit %d random interrupt\n", unit); return (MBN_SKIP); --- 387,390 ----- if ((er & MTER_INTCODE) != MTER_ONLINE) ! printf("mt: unit %d random interrupt\n", ! MUUNIT(bp->b_dev)); return (MBN_SKIP); *************** *** 379,384 } ! if (bp == 0) ! return (MBN_SKIP); ! fc = (mtaddr->mtncs[unit] >> 8) & 0xff; ! sc = &mu_softc[unit]; sc->sc_erreg = er; --- 391,393 ----- } ! fc = (mtaddr->mtncs[slave] >> 8) & 0xff; sc->sc_erreg = er; *************** Here's the mass driver addition: *** 492,493 return (0); } --- 501,517 ----- return (0); + } + + /* + * Start a ``raw block transfer'' from kernel space (via the + * mass driver). + */ + mtmass(bp) + register struct buf *bp; + { + register struct mu_softc *sc; + + minphys(bp); + sc = &mu_softc[MUUNIT(bp->b_dev)]; + sc->sc_blkno = bdbtofsb(bp->b_blkno); + sc->sc_nxrec = sc->sc_blkno + 1; } RCS file: RCS/param.h,v retrieving revision 1.1 diff -b -c1 -r1.1 param.h *** /tmp/,RCSt1003120 Fri Jan 4 22:59:49 1985 --- param.h Wed Jan 2 09:52:11 1985 *************** We like more processes and more files per process; this *************** has nothing to do with the mass driver. *** 18,21 #define MSWAPX 15 /* pseudo mount table index for swapdev */ ! #define MAXUPRC 25 /* max processes per user */ ! #define NOFILE 20 /* max open files per process */ /* NOFILE MUST NOT BE >= 31; SEE pte.h */ --- 18,21 ----- #define MSWAPX 15 /* pseudo mount table index for swapdev */ ! #define MAXUPRC 40 /* max processes per user */ ! #define NOFILE 30 /* max open files per process (std=20) */ /* NOFILE MUST NOT BE >= 31; SEE pte.h */ *************** We like more groups too. I recall a problem with UPAGES *************** getting too big if you increase NGROUPS, so you might want *************** to avoid this. *** 23,25 #define NCARGS 10240 /* # characters in exec arglist */ ! #define NGROUPS 8 /* max number groups */ --- 23,25 ----- #define NCARGS 10240 /* # characters in exec arglist */ ! #define NGROUPS 16 /* max number groups (std=8)*/ *************** I have most of the clist routines in VAX assembly, so I *************** moved the definitions to a separate file. You probably *************** don't want to do this. *** 97,100 ! #define CBSIZE 28 /* number of chars in a clist block */ ! #define CROUND 0x1F /* clist rounding; sizeof(int *) + CBSIZE -1*/ --- 97,103 ----- ! #ifndef KERNEL ! #include <sys/cblock.h> ! #else ! #include "../h/cblock.h" ! #endif *************** Fixing some comments... *** 116,118 * file systems; however making it smaller make make some file ! * systems unmountable. * --- 119,122 ----- * file systems; however making it smaller make make some file ! * systems unmountable. Also, note that MAXBSIZE must be >= MINBSIZE ! * (defined in ../h/fs.h). * *************** More comments, related to the way things are after adding *************** the mass driver. Install these if you are installing the *************** mass driver. *** 118,119 * * Note that the blocked devices are assumed to have DEV_BSIZE --- 122,134 ----- * + * MAXBSIZE is probably much larger than the average file system + * block, and it makes more sense to allocate buffers and memory + * based on the average size than on the maximum size. AVGBSIZE + * should be set to the "average" block size on your file systems. + * Setting it too small will mean that buffer memory will be scarce, + * while setting it too large will mean that buffers themselves will + * be the scarce resource. + * + * N.B.: MAXBSIZE must be a multiple of CLBYTES. Also, if you + * increase MAXBSIZE, you may have to increase SYSPTSIZE. + * * Note that the blocked devices are assumed to have DEV_BSIZE *************** The change to MAXBSIZE and the definition of AVGBSIZE *************** for the new code in vax/machdep.c. (I.e., the former *************** goes with the latter.) *** 127,129 */ ! #define MAXBSIZE 8192 #define DEV_BSIZE 512 --- 142,145 ----- */ ! #define MAXBSIZE 16384 /* was 8192 */ ! #define AVGBSIZE 4096 #define DEV_BSIZE 512 RCS file: RCS/ts.c,v retrieving revision 1.1 diff -b -c1 -r1.1 ts.c *** /tmp/,RCSt1003186 Fri Jan 4 23:01:16 1985 --- ts.c Wed Jan 2 11:57:07 1985 *************** Yet another useless conf.h *** 16,18 #include "../h/dir.h" - #include "../h/conf.h" #include "../h/user.h" --- 16,17 ----- #include "../h/dir.h" #include "../h/user.h" *************** Yet another BRL csleep change to ignore *** 296,298 bp->b_flags |= B_WANTED; ! sleep((caddr_t)bp, PRIBIO); } --- 295,297 ----- bp->b_flags |= B_WANTED; ! csleep((caddr_t)bp, PRIBIO, "TAPE"); } *************** I like type names. *** 509,511 int tsunit; ! register state; --- 508,510 ----- int tsunit; ! register int state; *************** This is necessary for the mass driver 'cause we need to *************** know the state ``inside'' biodone()... biodone may wind *************** up invoking the strategy routine, and we don't want it *************** calling tsstart() if the tape is really busy. *** 533,535 state = um->um_tab.b_active; - um->um_tab.b_active = 0; /* --- 532,533 ----- state = um->um_tab.b_active; /* *************** Formatting, formatting! Sheesh. *** 575,577 */ ! if (state==SIO) { if (++um->um_tab.b_errcnt < 7) { --- 573,575 ----- */ ! if (state == SIO) { if (++um->um_tab.b_errcnt < 7) { *************** Better state info. *** 660,662 iodone(bp); ! if (um->um_tab.b_actf->b_actf == 0) return; --- 658,661 ----- iodone(bp); ! if (um->um_tab.b_actf->b_actf == 0) { ! um->um_tab.b_active = 0; return; *************** *** 662,663 return; opcont: --- 661,663 ----- return; + } opcont: *************** The mass driver entry point. *** 733,734 return (0); } --- 733,750 ----- return (0); + } + + /* + * Start a ``raw block transfer'' from kernel space (via the + * mass driver). Job is a combination minphys() and part of + * tsphys(). + */ + tsmass(bp) + register struct buf *bp; + { + register struct ts_softc *sc; + + minphys(bp); + sc = &ts_softc[TSUNIT(bp->b_dev)]; + sc->sc_blkno = bdbtofsb(bp->b_blkno); + sc->sc_nxrec = sc->sc_blkno + 1; } RCS file: RCS/ufs_machdep.c,v retrieving revision 1.1 diff -b -c1 -r1.1 ufs_machdep.c *** /tmp/,RCSt1003161 Fri Jan 4 23:00:57 1985 --- ufs_machdep.c Wed Jan 2 10:42:31 1985 *************** Still another useless conf.h! Sigh. *** 9,11 #include "../h/buf.h" - #include "../h/conf.h" #include "../h/proc.h" --- 9,10 ----- #include "../h/buf.h" #include "../h/proc.h" *************** Gripe if someone asks for more space than exists in any *************** one buffer. *** 30,31 sizealloc = roundup(size, CLBYTES); /* --- 29,33 ----- sizealloc = roundup(size, CLBYTES); + if (sizealloc > MAXBSIZE) + panic("allocbuf"); + /* *************** Minor style thingy. I prefer parallel construction... *** 69,71 tp->b_bufsize += take; ! bp->b_bufsize = bp->b_bufsize - take; if (bp->b_bcount > bp->b_bufsize) --- 71,73 ----- tp->b_bufsize += take; ! bp->b_bufsize -= take; if (bp->b_bcount > bp->b_bufsize) RCS file: RCS/vm_mem.c,v retrieving revision 1.1 diff -b -c1 -r1.1 vm_mem.c *** /tmp/,RCSt1003130 Fri Jan 4 23:00:00 1985 --- vm_mem.c Wed Jan 2 10:24:43 1985 *************** More BRL csleep stuff to ignore *** 39,41 while (freemem == 0) ! sleep((caddr_t)&freemem, PSWP+2); m = imin(size, freemem); --- 39,41 ----- while (freemem == 0) ! csleep((caddr_t)&freemem, PSWP+2, "FREEMEM"); m = imin(size, freemem); *************** The C-compiler-sign-extension-bug fix (1 of 2; the other *************** is in some incredibly similar piece of code somewhere else *************** that I don't particularly recall.) *** 251,252 } if (mfind(c->c_mdev == MSWAPX ? --- 251,253 ----- } + #ifdef lint if (mfind(c->c_mdev == MSWAPX ? *************** *** 255,256 panic("memall mfind"); c1->c_mdev = 0; --- 256,263 ----- panic("memall mfind"); + #else /* Avoid compiler sign extend bug */ + if (mfind(c->c_mdev == MSWAPX ? + swapdev : mount[c->c_mdev].m_dev, + c->c_blkno)) + panic("memall mfind"); + #endif lint c1->c_mdev = 0; *************** A side dish of changes to make meminit complain about *************** improperly sized core maps, and to (probably) make the *************** generated code smaller too. *** 518,520 /* ! * Initialize core map */ --- 525,528 ----- /* ! * Initialize core map. Print a warning message if the core map is ! * too small to map everything, or another if it's way too big. */ *************** *** 523,525 { ! register int i; register struct cmap *c; --- 531,533 ----- { ! register int i, lastcm; register struct cmap *c; *************** *** 530,535 ecmx = ecmap - cmap; ! if (ecmx < freemem / CLSIZE) ! freemem = ecmx * CLSIZE; ! for (i = 1; i <= freemem / CLSIZE; i++) { ! cmap[i-1].c_next = i; c = &cmap[i]; --- 538,549 ----- ecmx = ecmap - cmap; ! lastcm = freemem / CLSIZE; ! if (ecmx < lastcm) { ! printf("core map %d too small (lost %d bytes of user mem)\n", ! lastcm - ecmx, freemem - ecmx * CLSIZE); ! lastcm = ecmx; ! freemem = lastcm * CLSIZE; ! } ! else if (ecmx - 20 > lastcm) /* probably shouldn't happen */ ! printf("%d unused core map entries\n", ecmx - lastcm); ! for (i = 1; i <= lastcm; i++) { c = &cmap[i]; *************** *** 535,536 c = &cmap[i]; c->c_prev = i-1; --- 549,551 ----- c = &cmap[i]; + c[-1].c_next = i; c->c_prev = i-1; *************** *** 542,544 } ! cmap[freemem / CLSIZE].c_next = CMHEAD; for (i = 0; i < CMHSIZ; i++) --- 557,561 ----- } ! cmap[CMHEAD].c_prev = lastcm; ! cmap[CMHEAD].c_type = CSYS; ! cmap[lastcm].c_next = CMHEAD; for (i = 0; i < CMHSIZ; i++) *************** *** 545,548 cmhash[i] = ecmx; - cmap[CMHEAD].c_prev = freemem / CLSIZE; - cmap[CMHEAD].c_type = CSYS; avefree = freemem; --- 562,563 ----- cmhash[i] = ecmx; avefree = freemem; *************** Yet another BRL csleep to ignore *** 577,579 c->c_want = 1; ! sleep((caddr_t)c, PSWP+1); } --- 592,594 ----- c->c_want = 1; ! csleep((caddr_t)c, PSWP+1, "PAGE"); } RCS file: RCS/vmparam.h,v retrieving revision 1.1 diff -b -c1 -r1.1 vmparam.h *** /tmp/,RCSt1003173 Fri Jan 4 23:01:05 1985 --- vmparam.h Wed Jan 2 10:43:06 1985 *************** We have bigger data and stack limits. Ignore these unless *************** you REALLY know what you're doing here. *** 26,28 #ifndef MAXDSIZ ! #define MAXDSIZ (12*1024-32-SLOP) /* max data size (clicks) */ #endif --- 26,28 ----- #ifndef MAXDSIZ ! #define MAXDSIZ (16*2048-32-SLOP) /* max data size (clicks) */ #endif *************** *** 28,30 #endif ! #define MAXSSIZ (12*1024-32-SLOP) /* max stack size (clicks) */ --- 28,30 ----- #endif ! #define MAXSSIZ (6*2048-32-SLOP) /* max stack size (clicks) */ *************** Increase SYSPTSIZE to handle mapping those 16K buffers. *************** The comment is right, but making it work that way is hard. *** 34,36 /* SYSPTSIZE IS SILLY; IT SHOULD BE COMPUTED AT BOOT TIME */ ! #define SYSPTSIZE ((20+MAXUSERS)*NPTEPG) #define USRPTSIZE (8*NPTEPG) --- 34,36 ----- /* SYSPTSIZE IS SILLY; IT SHOULD BE COMPUTED AT BOOT TIME */ ! #define SYSPTSIZE ((40+MAXUSERS)*NPTEPG) #define USRPTSIZE (8*NPTEPG) *************** Not sure exactly what this does, but it affects the *************** printf about "should use interleaved swap". *** 114,116 */ ! #define LOTSOFMEM 2 --- 114,116 ----- */ ! #define LOTSOFMEM 3 //go.sysin dd * made=TRUE if [ $made = TRUE ]; then /bin/chmod 644 kernel_mods /bin/echo -n ' '; /bin/ls -ld kernel_mods fi -- (This line accidently left nonblank.) In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (301) 454-7690 UUCP: {seismo,allegra,brl-bmd}!umcp-cs!chris CSNet: chris@umcp-cs ARPA: chris@maryland