Annotation of Net2/arch/tahoe/vba/vd.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1988 Regents of the University of California.
        !             3:  * All rights reserved.
        !             4:  *
        !             5:  * This code is derived from software contributed to Berkeley by
        !             6:  * Computer Consoles Inc.
        !             7:  *
        !             8:  * Redistribution and use in source and binary forms, with or without
        !             9:  * modification, are permitted provided that the following conditions
        !            10:  * are met:
        !            11:  * 1. Redistributions of source code must retain the above copyright
        !            12:  *    notice, this list of conditions and the following disclaimer.
        !            13:  * 2. Redistributions in binary form must reproduce the above copyright
        !            14:  *    notice, this list of conditions and the following disclaimer in the
        !            15:  *    documentation and/or other materials provided with the distribution.
        !            16:  * 3. All advertising materials mentioning features or use of this software
        !            17:  *    must display the following acknowledgement:
        !            18:  *     This product includes software developed by the University of
        !            19:  *     California, Berkeley and its contributors.
        !            20:  * 4. Neither the name of the University nor the names of its contributors
        !            21:  *    may be used to endorse or promote products derived from this software
        !            22:  *    without specific prior written permission.
        !            23:  *
        !            24:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            25:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            26:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            27:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            28:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            29:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            30:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            31:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            32:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            33:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            34:  * SUCH DAMAGE.
        !            35:  *
        !            36:  *     @(#)vd.c        7.14 (Berkeley) 4/1/91
        !            37:  */
        !            38: 
        !            39: #include "dk.h"
        !            40: #if NVD > 0
        !            41: /*
        !            42:  * Versabus VDDC/SMDE driver.
        !            43:  */
        !            44: #include "sys/param.h"
        !            45: #include "sys/buf.h"
        !            46: #include "sys/cmap.h"
        !            47: #include "sys/conf.h"
        !            48: #include "sys/dkstat.h"
        !            49: #include "sys/disklabel.h"
        !            50: #include "sys/map.h"
        !            51: #include "sys/file.h"
        !            52: #include "sys/systm.h"
        !            53: #include "sys/user.h"
        !            54: #include "sys/vmmac.h"
        !            55: #include "sys/proc.h"
        !            56: #include "sys/syslog.h"
        !            57: #include "sys/kernel.h"
        !            58: #include "sys/ioctl.h"
        !            59: #include "sys/stat.h"
        !            60: 
        !            61: #include "../include/cpu.h"
        !            62: #include "../include/mtpr.h"
        !            63: #include "../include/pte.h"
        !            64: 
        !            65: #include "../vba/vbavar.h"
        !            66: #include "../vba/vdreg.h"
        !            67: 
        !            68: #ifndef        COMPAT_42
        !            69: #define        COMPAT_42
        !            70: #endif
        !            71: #define        B_FORMAT        B_XXX           /* XXX */
        !            72: 
        !            73: #define vdunit(dev)    (minor(dev) >> 3)
        !            74: #define vdpart(dev)    (minor(dev) & 0x07)
        !            75: #define        vdminor(unit,part)      (((unit) << 3) | (part))
        !            76: 
        !            77: struct vba_ctlr *vdminfo[NVD];
        !            78: struct  vba_device *vddinfo[NDK];
        !            79: int    vdprobe(), vdslave(), vdattach(), vddgo(), vdstrategy();
        !            80: long   vdstd[] = { 0xffff2000, 0xffff2100, 0xffff2200, 0xffff2300, 0 };
        !            81: struct vba_driver vddriver =
        !            82:   { vdprobe, vdslave, vdattach, vddgo, vdstd, "dk", vddinfo, "vd", vdminfo };
        !            83: 
        !            84: /*
        !            85:  * Per-controller state.
        !            86:  */
        !            87: struct vdsoftc {
        !            88:        u_short vd_flags;
        !            89: #define        VD_PRINT        0x1     /* controller info printed */
        !            90: #define        VD_STARTED      0x2     /* start command issued */
        !            91: #define        VD_DOSEEKS      0x4     /* should overlap seeks */
        !            92: #define        VD_SCATGATH     0x8     /* can do scatter-gather commands (correctly) */
        !            93: #define        VD_LOCKED       0x10    /* locked for direct controller access */
        !            94: #define        VD_WAIT         0x20    /* someone needs direct controller access */
        !            95:        u_short vd_type;        /* controller type */
        !            96:        u_short vd_wticks;      /* timeout */
        !            97:        u_short vd_secsize;     /* sector size for controller */
        !            98:        struct  mdcb vd_mdcb;   /* master command block */
        !            99:        u_long  vd_mdcbphys;    /* physical address of vd_mdcb */
        !           100:        struct  dcb vd_dcb;     /* i/o command block */
        !           101:        u_long  vd_dcbphys;     /* physical address of vd_dcb */
        !           102:        struct  vb_buf vd_rbuf; /* vba resources */
        !           103: } vdsoftc[NVD];
        !           104: 
        !           105: #define        VDMAXTIME       20      /* max time for operation, sec. */
        !           106: 
        !           107: /*
        !           108:  * Per-drive state.
        !           109:  */
        !           110: struct dksoftc {
        !           111:        int     dk_state;       /* open fsm */
        !           112: #ifndef SECSIZE
        !           113:        u_short dk_bshift;      /* shift for * (DEV_BSIZE / sectorsize) XXX */
        !           114: #endif SECSIZE
        !           115:        int     dk_wlabel;      /* label sector is currently writable */
        !           116:        u_long  dk_copenpart;   /* character units open on this drive */
        !           117:        u_long  dk_bopenpart;   /* block units open on this drive */
        !           118:        u_long  dk_openpart;    /* all units open on this drive */
        !           119:        u_int   dk_curcyl;      /* last selected cylinder */
        !           120:        struct  skdcb dk_dcb;   /* seek command block */
        !           121:        u_long  dk_dcbphys;     /* physical address of dk_dcb */
        !           122:        int     df_reg[3];      /* for formatting, in-out parameters */
        !           123: } dksoftc[NDK];
        !           124: 
        !           125: /*
        !           126:  * Drive states.  Used during steps of open/initialization.
        !           127:  * States < OPEN (> 0) are transient, during an open operation.
        !           128:  * OPENRAW is used for unlabeled disks, to allow format operations.
        !           129:  */
        !           130: #define        CLOSED          0               /* disk is closed */
        !           131: #define        WANTOPEN        1               /* open requested, not started */
        !           132: #define        WANTOPENRAW     2               /* open requested, no label */
        !           133: #define        RDLABEL         3               /* reading pack label */
        !           134: #define        OPEN            4               /* intialized and ready */
        !           135: #define        OPENRAW         5               /* open, no label */
        !           136: 
        !           137: struct buf dkutab[NDK];        /* i/o queue headers */
        !           138: struct disklabel dklabel[NDK]; /* pack labels */
        !           139: 
        !           140: #define b_cylin        b_resid
        !           141: #define        b_track b_error         /* used for seek commands */
        !           142: #define        b_seekf b_forw          /* second queue on um_tab */
        !           143: #define        b_seekl b_back          /* second queue on um_tab */
        !           144: 
        !           145: int    vdwstart, vdwatch();
        !           146: 
        !           147: /*
        !           148:  * See if the controller is really there; if so, initialize it.
        !           149:  */
        !           150: vdprobe(reg, vm)
        !           151:        caddr_t reg;
        !           152:        struct vba_ctlr *vm;
        !           153: {
        !           154:        register br, cvec;              /* must be r12, r11 */
        !           155:        register struct vddevice *vdaddr = (struct vddevice *)reg;
        !           156:        struct vdsoftc *vd;
        !           157:        int s;
        !           158: 
        !           159: #ifdef lint
        !           160:        br = 0; cvec = br; br = cvec;
        !           161:        vdintr(0);
        !           162: #endif
        !           163:        if (badaddr((caddr_t)reg, 2))
        !           164:                return (0);
        !           165:        vd = &vdsoftc[vm->um_ctlr];
        !           166:        vdaddr->vdreset = 0xffffffff;
        !           167:        DELAY(1000000);
        !           168:        if (vdaddr->vdreset != (unsigned)0xffffffff) {
        !           169:                vd->vd_type = VDTYPE_VDDC;
        !           170:                vd->vd_flags &= ~VD_DOSEEKS;
        !           171:                DELAY(1000000);
        !           172:        } else {
        !           173:                vd->vd_type = VDTYPE_SMDE;
        !           174:                vd->vd_flags |= VD_DOSEEKS;
        !           175:                vdaddr->vdrstclr = 0;
        !           176:                DELAY(3000000);
        !           177:        }
        !           178:        vd->vd_mdcbphys = vtoph((struct proc *)0, (unsigned)&vd->vd_mdcb);
        !           179:        vd->vd_dcbphys = vtoph((struct proc *)0, (unsigned)&vd->vd_dcb);
        !           180:        vm->um_addr = reg;              /* XXX */
        !           181:        s = spl7();
        !           182:        if (vdinit_ctlr(vm, vd) == 0) {
        !           183:                splx(s);
        !           184:                return (0);
        !           185:        }
        !           186:        if (vd->vd_type == VDTYPE_SMDE) {
        !           187: #ifdef notdef
        !           188:                /*
        !           189:                 * Attempt PROBE to get all drive status;
        !           190:                 * we take advantage of this in vdreset_drive
        !           191:                 * to try to avoid guessing games.
        !           192:                 */
        !           193:                (void) vdcmd(vm, VDOP_PROBE, 5, 0);
        !           194: #endif
        !           195:                /*
        !           196:                 * Check for scatter-gather by checking firmware date
        !           197:                 * with IDENT command.  The date is printed when
        !           198:                 * vdslave is first called, thus this must be
        !           199:                 * the last controller operation in vdprobe.
        !           200:                 */
        !           201:                vd->vd_dcb.trail.idtrail.date = 0;
        !           202:                if (vdcmd(vm, VDOP_IDENT, 10, 0)) {
        !           203:                        uncache(&vd->vd_dcb.trail.idtrail.date);
        !           204:                        if (vd->vd_dcb.trail.idtrail.date != 0)
        !           205:                                vd->vd_flags |= VD_SCATGATH;
        !           206:                }
        !           207:        }
        !           208:        splx(s);
        !           209:        /*
        !           210:         * Allocate page tables and i/o buffer.
        !           211:         */
        !           212:        if (vbainit(&vd->vd_rbuf, MAXPHYS,
        !           213:            vd->vd_type == VDTYPE_VDDC ? VB_24BIT : VB_32BIT) == 0) {
        !           214:                printf("vd%d: vbainit failed\n", vm->um_ctlr);
        !           215:                return (0);
        !           216:        }
        !           217:        br = 0x17, cvec = 0xe0 + vm->um_ctlr;   /* XXX */
        !           218:        return (sizeof (struct vddevice));
        !           219: }
        !           220: 
        !           221: /*
        !           222:  * See if a drive is really there.
        !           223:  *
        !           224:  * Can't read pack label here as various data structures
        !           225:  * aren't setup for doing a read in a straightforward
        !           226:  * manner.  Instead just probe for the drive and leave
        !           227:  * the pack label stuff to the attach routine.
        !           228:  */
        !           229: /* ARGSUSED */
        !           230: vdslave(vi, vdaddr)
        !           231:        register struct vba_device *vi;
        !           232:        struct vddevice *vdaddr;
        !           233: {
        !           234:        register struct disklabel *lp = &dklabel[vi->ui_unit];
        !           235:        register struct dksoftc *dk = &dksoftc[vi->ui_unit];
        !           236:        struct vdsoftc *vd = &vdsoftc[vi->ui_ctlr];
        !           237:        int bcd();
        !           238: 
        !           239:        if ((vd->vd_flags&VD_PRINT) == 0) {
        !           240:                printf("vd%d: %s controller", vi->ui_ctlr,
        !           241:                    vd->vd_type == VDTYPE_VDDC ? "VDDC" : "SMDE");
        !           242:                if (vd->vd_flags & VD_SCATGATH) {
        !           243:                        char rev[5];
        !           244: 
        !           245:                        bcopy((caddr_t)&vd->vd_dcb.trail.idtrail.rev, rev,
        !           246:                            sizeof(vd->vd_dcb.trail.idtrail.rev));
        !           247:                        printf(" firmware rev %s (%d-%d-%d)", rev,
        !           248:                            bcd((vd->vd_dcb.trail.idtrail.date >> 8) & 0xff),
        !           249:                            bcd(vd->vd_dcb.trail.idtrail.date & 0xff),
        !           250:                            bcd((vd->vd_dcb.trail.idtrail.date >> 16)&0xffff));
        !           251:                }
        !           252:                printf("\n");
        !           253:                vd->vd_flags |= VD_PRINT;
        !           254:        }
        !           255: 
        !           256:        /*
        !           257:         * Initialize label enough to do a reset on
        !           258:         * the drive.  The remainder of the default
        !           259:         * label values will be filled in in vdinit
        !           260:         * at attach time.
        !           261:         */
        !           262:        if (vd->vd_type == VDTYPE_SMDE)
        !           263:                lp->d_secsize = VD_MAXSECSIZE;
        !           264:        else
        !           265:                lp->d_secsize = VDDC_SECSIZE;
        !           266:        lp->d_nsectors = 66;            /* only used on smd-e */
        !           267:        lp->d_ntracks = 23;
        !           268:        lp->d_ncylinders = 850;
        !           269:        lp->d_secpercyl = 66*23;
        !           270:        lp->d_rpm = 3600;
        !           271:        lp->d_npartitions = 1;
        !           272:        lp->d_partitions[0].p_offset = 0;
        !           273:        lp->d_partitions[0].p_size = LABELSECTOR + 1;
        !           274: 
        !           275:        /*
        !           276:         * Initialize invariant portion of
        !           277:         * dcb used for overlapped seeks.
        !           278:         */
        !           279:        dk->dk_dcb.opcode = VDOP_SEEK;
        !           280:        dk->dk_dcb.intflg = DCBINT_NONE | DCBINT_PBA;
        !           281:        dk->dk_dcb.devselect = vi->ui_slave;
        !           282:        dk->dk_dcb.trailcnt = sizeof (struct trseek) / sizeof (long);
        !           283:        dk->dk_dcb.trail.sktrail.skaddr.sector = 0;
        !           284:        dk->dk_dcbphys = vtoph((struct proc *)0, (unsigned)&dk->dk_dcb);
        !           285: #ifndef SECSIZE
        !           286:        vd_setsecsize(dk, lp);
        !           287: #endif
        !           288:        return (vdreset_drive(vi));
        !           289: }
        !           290: 
        !           291: static int
        !           292: bcd(n)
        !           293:        register u_int n;
        !           294: {
        !           295:        register int bin = 0;
        !           296:        register int mul = 1;
        !           297: 
        !           298:        while (n) {
        !           299:                bin += (n & 0xf) * mul;
        !           300:                n >>= 4;
        !           301:                mul *= 10;
        !           302:        }
        !           303:        return (bin);
        !           304: }
        !           305: 
        !           306: vdattach(vi)
        !           307:        register struct vba_device *vi;
        !           308: {
        !           309:        register int unit = vi->ui_unit;
        !           310:        register struct disklabel *lp = &dklabel[unit];
        !           311: 
        !           312:        /*
        !           313:         * Try to initialize device and read pack label.
        !           314:         */
        !           315:        if (vdinit(vdminor(unit, 0), 0) != 0) {
        !           316:                printf(": unknown drive type");
        !           317:                return;
        !           318:        }
        !           319:        if (dksoftc[unit].dk_state == OPEN)
        !           320:                printf(": %s <secsize %d, ntrak %d, ncyl %d, nsec %d>",
        !           321:                    lp->d_typename, lp->d_secsize,
        !           322:                    lp->d_ntracks, lp->d_ncylinders, lp->d_nsectors);
        !           323:        /*
        !           324:         * (60 / rpm) / (sectors per track * (bytes per sector / 2))
        !           325:         */
        !           326:        if (vi->ui_dk >= 0)
        !           327:                dk_wpms[vi->ui_dk] =
        !           328:                    (lp->d_rpm * lp->d_nsectors * lp->d_secsize) / 120;
        !           329: #ifdef notyet
        !           330:        addswap(makedev(VDMAJOR, vdminor(unit, 0)), lp);
        !           331: #endif
        !           332: }
        !           333: 
        !           334: vdopen(dev, flags, fmt)
        !           335:        dev_t dev;
        !           336:        int flags, fmt;
        !           337: {
        !           338:        register unit = vdunit(dev);
        !           339:        register struct disklabel *lp;
        !           340:        register struct dksoftc *dk;
        !           341:        register struct partition *pp;
        !           342:        struct vba_device *vi;
        !           343:        int s, error = 0, part = vdpart(dev), mask = 1 << part;
        !           344:        daddr_t start, end;
        !           345: 
        !           346:        if (unit >= NDK || (vi = vddinfo[unit]) == 0 || vi->ui_alive == 0)
        !           347:                return (ENXIO);
        !           348:        lp = &dklabel[unit];
        !           349:        dk = &dksoftc[unit];
        !           350: 
        !           351:        s = spl7();
        !           352:        while (dk->dk_state != OPEN && dk->dk_state != OPENRAW &&
        !           353:            dk->dk_state != CLOSED)
        !           354:                if (error = tsleep((caddr_t)dk, (PZERO+1) | PCATCH, devopn, 0))
        !           355:                        break;
        !           356:        splx(s);
        !           357:        if (error)
        !           358:                return (error);
        !           359:        if (dk->dk_state != OPEN && dk->dk_state != OPENRAW)
        !           360:                if (error = vdinit(dev, flags))
        !           361:                        return (error);
        !           362: 
        !           363:        if (vdwstart == 0) {
        !           364:                timeout(vdwatch, (caddr_t)0, hz);
        !           365:                vdwstart++;
        !           366:        }
        !           367:        /*
        !           368:         * Warn if a partion is opened
        !           369:         * that overlaps another partition which is open
        !           370:         * unless one is the "raw" partition (whole disk).
        !           371:         */
        !           372: #define        RAWPART         8               /* 'x' partition */     /* XXX */
        !           373:        if ((dk->dk_openpart & mask) == 0 && part != RAWPART) {
        !           374:                pp = &lp->d_partitions[part];
        !           375:                start = pp->p_offset;
        !           376:                end = pp->p_offset + pp->p_size;
        !           377:                for (pp = lp->d_partitions;
        !           378:                     pp < &lp->d_partitions[lp->d_npartitions]; pp++) {
        !           379:                        if (pp->p_offset + pp->p_size <= start ||
        !           380:                            pp->p_offset >= end)
        !           381:                                continue;
        !           382:                        if (pp - lp->d_partitions == RAWPART)
        !           383:                                continue;
        !           384:                        if (dk->dk_openpart & (1 << (pp - lp->d_partitions)))
        !           385:                                log(LOG_WARNING,
        !           386:                                    "dk%d%c: overlaps open partition (%c)\n",
        !           387:                                    unit, part + 'a',
        !           388:                                    pp - lp->d_partitions + 'a');
        !           389:                }
        !           390:        }
        !           391:        if (part >= lp->d_npartitions)
        !           392:                return (ENXIO);
        !           393:        dk->dk_openpart |= mask;
        !           394:        switch (fmt) {
        !           395:        case S_IFCHR:
        !           396:                dk->dk_copenpart |= mask;
        !           397:                break;
        !           398:        case S_IFBLK:
        !           399:                dk->dk_bopenpart |= mask;
        !           400:                break;
        !           401:        }
        !           402:        return (0);
        !           403: }
        !           404: 
        !           405: /* ARGSUSED */
        !           406: vdclose(dev, flags, fmt)
        !           407:        dev_t dev;
        !           408:        int flags, fmt;
        !           409: {
        !           410:        register int unit = vdunit(dev);
        !           411:        register struct dksoftc *dk = &dksoftc[unit];
        !           412:        int part = vdpart(dev), mask = 1 << part;
        !           413: 
        !           414:        switch (fmt) {
        !           415:        case S_IFCHR:
        !           416:                dk->dk_copenpart &= ~mask;
        !           417:                break;
        !           418:        case S_IFBLK:
        !           419:                dk->dk_bopenpart &= ~mask;
        !           420:                break;
        !           421:        }
        !           422:        if (((dk->dk_copenpart | dk->dk_bopenpart) & mask) == 0)
        !           423:                dk->dk_openpart &= ~mask;
        !           424:        /*
        !           425:         * Should wait for i/o to complete on this partition
        !           426:         * even if others are open, but wait for work on blkflush().
        !           427:         */
        !           428:        if (dk->dk_openpart == 0) {
        !           429:                int s = spl7();
        !           430:                while (dkutab[unit].b_actf)
        !           431:                        sleep((caddr_t)dk, PZERO-1);
        !           432:                splx(s);
        !           433:                dk->dk_state = CLOSED;
        !           434:                dk->dk_wlabel = 0;
        !           435:        }
        !           436:        return (0);
        !           437: }
        !           438: 
        !           439: vdinit(dev, flags)
        !           440:        dev_t dev;
        !           441:        int flags;
        !           442: {
        !           443:        register struct disklabel *lp;
        !           444:        register struct dksoftc *dk;
        !           445:        struct vba_device *vi;
        !           446:        int unit = vdunit(dev), error = 0;
        !           447:        char *msg, *readdisklabel();
        !           448:        extern int cold;
        !           449: 
        !           450:        dk = &dksoftc[unit];
        !           451:        if (flags & O_NDELAY) {
        !           452:                dk->dk_state = OPENRAW;
        !           453:                return (0);
        !           454:        }
        !           455:        dk->dk_state = RDLABEL;
        !           456:        lp = &dklabel[unit];
        !           457:        vi = vddinfo[unit];
        !           458:        if (msg = readdisklabel(dev, vdstrategy, lp)) {
        !           459:                if (cold) {
        !           460:                        printf(": %s", msg);
        !           461:                        dk->dk_state = CLOSED;
        !           462:                } else {
        !           463:                        log(LOG_ERR, "dk%d: %s\n", unit, msg);
        !           464:                        dk->dk_state = OPENRAW;
        !           465:                }
        !           466: #ifdef COMPAT_42
        !           467:                vdlock(vi->ui_ctlr);
        !           468:                if (vdmaptype(vi, lp))
        !           469:                        dk->dk_state = OPEN;
        !           470:                vdunlock(vi->ui_ctlr);
        !           471: #endif
        !           472:        } else {
        !           473:                /*
        !           474:                 * Now that we have the label, configure
        !           475:                 * the correct drive parameters.
        !           476:                 */
        !           477:                vdlock(vi->ui_ctlr);
        !           478:                if (vdreset_drive(vi))
        !           479:                        dk->dk_state = OPEN;
        !           480:                else {
        !           481:                        dk->dk_state = CLOSED;
        !           482:                        error = ENXIO;
        !           483:                }
        !           484:                vdunlock(vi->ui_ctlr);
        !           485:        }
        !           486: #ifndef SECSIZE
        !           487:        vd_setsecsize(dk, lp);
        !           488: #endif
        !           489:        wakeup((caddr_t)dk);
        !           490:        return (error);
        !           491: }
        !           492: 
        !           493: #ifndef SECSIZE
        !           494: vd_setsecsize(dk, lp)
        !           495:        register struct dksoftc *dk;
        !           496:        register struct disklabel *lp;
        !           497: {
        !           498:        int mul;
        !           499: 
        !           500:        /*
        !           501:         * Calculate scaling shift for mapping
        !           502:         * DEV_BSIZE blocks to drive sectors.
        !           503:         */
        !           504:        mul = DEV_BSIZE / lp->d_secsize;
        !           505:        dk->dk_bshift = 0;
        !           506:        while ((mul >>= 1) > 0)
        !           507:                dk->dk_bshift++;
        !           508: }
        !           509: #endif SECSIZE
        !           510: 
        !           511: /*ARGSUSED*/
        !           512: vddgo(vm)
        !           513:        struct vba_device *vm;
        !           514: {
        !           515: 
        !           516: }
        !           517: 
        !           518: vdstrategy(bp)
        !           519:        register struct buf *bp;
        !           520: {
        !           521:        register struct vba_device *vi;
        !           522:        register struct disklabel *lp;
        !           523:        register struct dksoftc *dk;
        !           524:        register int unit;
        !           525:        register daddr_t sn;
        !           526:        struct buf *dp;
        !           527:        daddr_t sz, maxsz;
        !           528:        int part, s;
        !           529: 
        !           530:        unit = vdunit(bp->b_dev);
        !           531:        if (unit >= NDK) {
        !           532:                bp->b_error = ENXIO;
        !           533:                goto bad;
        !           534:        }
        !           535:        vi = vddinfo[unit];
        !           536:        lp = &dklabel[unit];
        !           537:        if (vi == 0 || vi->ui_alive == 0) {
        !           538:                bp->b_error = ENXIO;
        !           539:                goto bad;
        !           540:        }
        !           541:        dk = &dksoftc[unit];
        !           542:        if (dk->dk_state < OPEN) {
        !           543:                if (dk->dk_state == CLOSED) {
        !           544:                        bp->b_error = EIO;
        !           545:                        goto bad;
        !           546:                }
        !           547:                goto q;
        !           548:        }
        !           549:        if (dk->dk_state != OPEN && (bp->b_flags & B_READ) == 0) {
        !           550:                bp->b_error = EROFS;
        !           551:                goto bad;
        !           552:        }
        !           553:        part = vdpart(bp->b_dev);
        !           554:        if ((dk->dk_openpart & (1 << part)) == 0) {
        !           555:                bp->b_error = ENODEV;
        !           556:                goto bad;
        !           557:        }
        !           558:        sz = (bp->b_bcount + lp->d_secsize - 1) / lp->d_secsize;
        !           559:        maxsz = lp->d_partitions[part].p_size;
        !           560: #ifndef SECSIZE
        !           561:        sn = bp->b_blkno << dk->dk_bshift;
        !           562: #else SECSIZE
        !           563:        sn = bp->b_blkno;
        !           564: #endif SECSIZE
        !           565:        if (sn + lp->d_partitions[part].p_offset <= LABELSECTOR &&
        !           566: #if LABELSECTOR != 0
        !           567:            sn + lp->d_partitions[part].p_offset + sz > LABELSECTOR &&
        !           568: #endif
        !           569:            (bp->b_flags & B_READ) == 0 && dk->dk_wlabel == 0) {
        !           570:                bp->b_error = EROFS;
        !           571:                goto bad;
        !           572:        }
        !           573:        if (sn < 0 || sn + sz > maxsz) {
        !           574:                if (sn == maxsz) {
        !           575:                        bp->b_resid = bp->b_bcount;
        !           576:                        goto done;
        !           577:                }
        !           578:                sz = maxsz - sn;
        !           579:                if (sz <= 0) {
        !           580:                        bp->b_error = EINVAL;
        !           581:                        goto bad;
        !           582:                }
        !           583:                bp->b_bcount = sz * lp->d_secsize;
        !           584:        }
        !           585:        bp->b_cylin = (sn + lp->d_partitions[part].p_offset) / lp->d_secpercyl;
        !           586: #ifdef SECSIZE
        !           587: if (bp->b_blksize != lp->d_secsize && (bp->b_flags & B_PGIN) == 0)
        !           588: panic("vdstrat blksize");
        !           589: #endif SECSIZE
        !           590: q:
        !           591:        s = spl7();
        !           592:        dp = &dkutab[vi->ui_unit];
        !           593:        disksort(dp, bp);
        !           594:        if (!dp->b_active) {
        !           595:                (void) vdustart(vi);
        !           596:                if (!vi->ui_mi->um_tab.b_active)
        !           597:                        vdstart(vi->ui_mi);
        !           598:        }
        !           599:        splx(s);
        !           600:        return;
        !           601: bad:   
        !           602:        bp->b_flags |= B_ERROR;
        !           603: done:
        !           604:        biodone(bp);
        !           605:        return;
        !           606: }
        !           607: 
        !           608: vdustart(vi)
        !           609:        register struct vba_device *vi;
        !           610: {
        !           611:        register struct buf *bp, *dp;
        !           612:        register struct vba_ctlr *vm;
        !           613:        register int unit = vi->ui_unit;
        !           614:        register struct dksoftc *dk;
        !           615:        register struct vdsoftc *vd;
        !           616:        struct disklabel *lp;
        !           617: 
        !           618:        dp = &dkutab[unit];
        !           619:        /*
        !           620:         * If queue empty, nothing to do.
        !           621:         */
        !           622:        if ((bp = dp->b_actf) == NULL)
        !           623:                return;
        !           624:        /*
        !           625:         * If drive is off-cylinder and controller supports seeks,
        !           626:         * place drive on seek queue for controller.
        !           627:         * Otherwise, place on transfer queue.
        !           628:         */
        !           629:        vd = &vdsoftc[vi->ui_ctlr];
        !           630:        dk = &dksoftc[unit];
        !           631:        vm = vi->ui_mi;
        !           632:        if (bp->b_cylin != dk->dk_curcyl && vd->vd_flags&VD_DOSEEKS) {
        !           633:                lp = &dklabel[unit];
        !           634:                bp->b_track = (bp->b_blkno % lp->d_secpercyl) / lp->d_nsectors;
        !           635:                if (vm->um_tab.b_seekf == NULL)
        !           636:                        vm->um_tab.b_seekf = dp;
        !           637:                else
        !           638:                        vm->um_tab.b_seekl->b_forw = dp;
        !           639:                vm->um_tab.b_seekl = dp;
        !           640:        } else {
        !           641:                if (vm->um_tab.b_actf == NULL)
        !           642:                        vm->um_tab.b_actf = dp;
        !           643:                else
        !           644:                        vm->um_tab.b_actl->b_forw = dp;
        !           645:                vm->um_tab.b_actl = dp;
        !           646:        }
        !           647:        dp->b_forw = NULL;
        !           648:        dp->b_active++;
        !           649: }
        !           650: 
        !           651: /*
        !           652:  * Start next transfer on a controller.
        !           653:  * There are two queues of drives, the first on-cylinder
        !           654:  * and the second off-cylinder from their next transfers.
        !           655:  * Perform the first transfer for the first drive on the on-cylinder
        !           656:  * queue, if any, otherwise the first transfer for the first drive
        !           657:  * on the second queue.  Initiate seeks on remaining drives on the
        !           658:  * off-cylinder queue, then move them all to the on-cylinder queue.
        !           659:  */
        !           660: vdstart(vm)
        !           661:        register struct vba_ctlr *vm;
        !           662: {
        !           663:        register struct buf *bp;
        !           664:        register struct vba_device *vi;
        !           665:        register struct vdsoftc *vd;
        !           666:        register struct dksoftc *dk;
        !           667:        register struct disklabel *lp;
        !           668:        register struct dcb **dcbp;
        !           669:        struct buf *dp;
        !           670:        int sn, tn;
        !           671: 
        !           672: loop:
        !           673:        /*
        !           674:         * Pull a request off the controller queue.
        !           675:         */
        !           676:        if ((dp = vm->um_tab.b_actf) == NULL &&
        !           677:            (dp = vm->um_tab.b_seekf) == NULL)
        !           678:                return;
        !           679:        if ((bp = dp->b_actf) == NULL) {
        !           680:                if (dp == vm->um_tab.b_actf)
        !           681:                        vm->um_tab.b_actf = dp->b_forw;
        !           682:                else
        !           683:                        vm->um_tab.b_seekf = dp->b_forw;
        !           684:                goto loop;
        !           685:        }
        !           686: 
        !           687:        /*
        !           688:         * Mark controller busy, and determine
        !           689:         * destination of this request.
        !           690:         */
        !           691:        vm->um_tab.b_active++;
        !           692:        vi = vddinfo[vdunit(bp->b_dev)];
        !           693:        dk = &dksoftc[vi->ui_unit];
        !           694: #ifndef SECSIZE
        !           695:        sn = bp->b_blkno << dk->dk_bshift;
        !           696: #else SECSIZE
        !           697:        sn = bp->b_blkno;
        !           698: #endif SECSIZE
        !           699:        lp = &dklabel[vi->ui_unit];
        !           700:        sn %= lp->d_secpercyl;
        !           701:        tn = sn / lp->d_nsectors;
        !           702:        sn %= lp->d_nsectors;
        !           703: 
        !           704:        /*
        !           705:         * Construct dcb for read/write command.
        !           706:         */
        !           707:        vd = &vdsoftc[vm->um_ctlr];
        !           708:        vd->vd_dcb.intflg = DCBINT_DONE;
        !           709:        vd->vd_dcb.devselect = dk->dk_dcb.devselect;
        !           710:        vd->vd_dcb.operrsta = 0;
        !           711:        vd->vd_dcb.nxtdcb = (struct dcb *)0;    /* end of chain */
        !           712:        vd->vd_dcb.trail.rwtrail.disk.cylinder = bp->b_cylin;
        !           713:        vd->vd_dcb.trail.rwtrail.disk.track = tn;
        !           714:        vd->vd_dcb.trail.rwtrail.disk.sector = sn;
        !           715:        dk->dk_curcyl = bp->b_cylin;
        !           716:        bp->b_track = 0;                /* init overloaded field */
        !           717:        vd->vd_dcb.trailcnt = sizeof (struct trrw) / sizeof (long);
        !           718:        if (bp->b_flags & B_FORMAT)
        !           719:                vd->vd_dcb.opcode = dk->dk_op;
        !           720:        else if (vd->vd_flags & VD_SCATGATH &&
        !           721:            ((int)bp->b_un.b_addr & (sizeof(long) - 1)) == 0)
        !           722:                vd->vd_dcb.opcode = (bp->b_flags & B_READ)? VDOP_RAS : VDOP_GAW;
        !           723:        else
        !           724:                vd->vd_dcb.opcode = (bp->b_flags & B_READ)? VDOP_RD : VDOP_WD;
        !           725: 
        !           726:        switch (vd->vd_dcb.opcode) {
        !           727:        case VDOP_FSECT:
        !           728:                vd->vd_dcb.trailcnt = sizeof (struct trfmt) / sizeof (long);
        !           729:                vd->vd_dcb.trail.fmtrail.nsectors = bp->b_bcount /
        !           730:                    lp->d_secsize;
        !           731:                vd->vd_dcb.trail.fmtrail.hdr = *(dskadr *)&dk->dk_althdr;
        !           732:                vd->vd_dcb.trail.rwtrail.disk.cylinder |= dk->dk_fmtflags;
        !           733:                goto setupaddr;
        !           734: 
        !           735:        case VDOP_RDRAW:
        !           736:        case VDOP_RD:
        !           737:        case VDOP_RHDE:
        !           738:        case VDOP_WD:
        !           739:                vd->vd_dcb.trail.rwtrail.wcount = (bp->b_bcount+1) >> 1;
        !           740: setupaddr:
        !           741:                vd->vd_dcb.trail.rwtrail.memadr =
        !           742:                        vbasetup(bp, &vd->vd_rbuf, (int)lp->d_secsize);
        !           743:                break;
        !           744: 
        !           745:        case VDOP_RAS:
        !           746:        case VDOP_GAW:
        !           747:                vd->vd_dcb.trailcnt += vd_sgsetup(bp, &vd->vd_rbuf,
        !           748:                    &vd->vd_dcb.trail.sgtrail);
        !           749:                break;
        !           750:        }
        !           751:        if (vi->ui_dk >= 0) {
        !           752:                dk_busy |= 1<<vi->ui_dk;
        !           753:                dk_xfer[vi->ui_dk]++;
        !           754:                dk_wds[vi->ui_dk] += bp->b_bcount>>6;
        !           755:        }
        !           756: 
        !           757:        /*
        !           758:         * Look for any seeks to be performed on other drives on this
        !           759:         * controller.  If overlapped seeks exist, insert seek commands
        !           760:         * on the controller's command queue before the transfer.
        !           761:         */
        !           762:        dcbp = &vd->vd_mdcb.mdcb_head;
        !           763: 
        !           764:        if (dp == vm->um_tab.b_seekf)
        !           765:                dp = dp->b_forw;
        !           766:        else
        !           767:                dp = vm->um_tab.b_seekf;
        !           768:        for (; dp != NULL; dp = dp->b_forw) {
        !           769:                if ((bp = dp->b_actf) == NULL)
        !           770:                        continue;
        !           771:                vi = vddinfo[vdunit(bp->b_dev)];
        !           772:                dk = &dksoftc[vi->ui_unit];
        !           773:                dk->dk_curcyl = bp->b_cylin;
        !           774:                if (vi->ui_dk >= 0)
        !           775:                        dk_seek[vi->ui_dk]++;
        !           776:                dk->dk_dcb.operrsta = 0;
        !           777:                dk->dk_dcb.trail.sktrail.skaddr.cylinder = bp->b_cylin;
        !           778:                dk->dk_dcb.trail.sktrail.skaddr.track = bp->b_track;
        !           779:                *dcbp = (struct dcb *)dk->dk_dcbphys;
        !           780:                dcbp = &dk->dk_dcb.nxtdcb;
        !           781:        }
        !           782:        *dcbp = (struct dcb *)vd->vd_dcbphys;
        !           783:        if (vm->um_tab.b_actf)
        !           784:                vm->um_tab.b_actl->b_forw = vm->um_tab.b_seekf;
        !           785:        else
        !           786:                vm->um_tab.b_actf = vm->um_tab.b_seekf;
        !           787:        if (vm->um_tab.b_seekf)
        !           788:                vm->um_tab.b_actl = vm->um_tab.b_seekl;
        !           789:        vm->um_tab.b_seekf = 0;
        !           790: 
        !           791:        /*
        !           792:         * Initiate operation.
        !           793:         */
        !           794:        vd->vd_mdcb.mdcb_status = 0;
        !           795:        VDGO(vm->um_addr, vd->vd_mdcbphys, vd->vd_type);
        !           796: }
        !           797: 
        !           798: /*
        !           799:  * Wait for controller to finish current operation
        !           800:  * so that direct controller accesses can be done.
        !           801:  */
        !           802: vdlock(ctlr)
        !           803: {
        !           804:        register struct vba_ctlr *vm = vdminfo[ctlr];
        !           805:        register struct vdsoftc *vd = &vdsoftc[ctlr];
        !           806:        int s;
        !           807: 
        !           808:        s = spl7();
        !           809:        while (vm->um_tab.b_active || vd->vd_flags & VD_LOCKED) {
        !           810:                vd->vd_flags |= VD_WAIT;
        !           811:                sleep((caddr_t)vd, PRIBIO);
        !           812:        }
        !           813:        vd->vd_flags |= VD_LOCKED;
        !           814:        splx(s);
        !           815: }
        !           816: 
        !           817: /*
        !           818:  * Continue normal operations after pausing for 
        !           819:  * munging the controller directly.
        !           820:  */
        !           821: vdunlock(ctlr)
        !           822: {
        !           823:        register struct vba_ctlr *vm = vdminfo[ctlr];
        !           824:        register struct vdsoftc *vd = &vdsoftc[ctlr];
        !           825: 
        !           826:        vd->vd_flags &= ~VD_LOCKED;
        !           827:        if (vd->vd_flags & VD_WAIT) {
        !           828:                vd->vd_flags &= ~VD_WAIT;
        !           829:                wakeup((caddr_t)vd);
        !           830:        } else if (vm->um_tab.b_actf || vm->um_tab.b_seekf)
        !           831:                vdstart(vm);
        !           832: }
        !           833: 
        !           834: #define        DONTCARE (DCBS_DSE|DCBS_DSL|DCBS_TOP|DCBS_TOM|DCBS_FAIL|DCBS_DONE)
        !           835: /*
        !           836:  * Handle a disk interrupt.
        !           837:  */
        !           838: vdintr(ctlr)
        !           839:        register ctlr;
        !           840: {
        !           841:        register struct buf *bp, *dp;
        !           842:        register struct vba_ctlr *vm = vdminfo[ctlr];
        !           843:        register struct vba_device *vi;
        !           844:        register struct vdsoftc *vd = &vdsoftc[ctlr];
        !           845:        register status;
        !           846:        int timedout;
        !           847:        struct dksoftc *dk;
        !           848: 
        !           849:        if (!vm->um_tab.b_active) {
        !           850:                printf("vd%d: stray interrupt\n", ctlr);
        !           851:                return;
        !           852:        }
        !           853:        /*
        !           854:         * Get device and block structures, and a pointer
        !           855:         * to the vba_device for the drive.
        !           856:         */
        !           857:        dp = vm->um_tab.b_actf;
        !           858:        bp = dp->b_actf;
        !           859:        vi = vddinfo[vdunit(bp->b_dev)];
        !           860:        dk = &dksoftc[vi->ui_unit];
        !           861:        if (vi->ui_dk >= 0)
        !           862:                dk_busy &= ~(1<<vi->ui_dk);
        !           863:        timedout = (vd->vd_wticks >= VDMAXTIME);
        !           864:        /*
        !           865:         * Check for and process errors on
        !           866:         * either the drive or the controller.
        !           867:         */
        !           868:        uncache(&vd->vd_dcb.operrsta);
        !           869:        status = vd->vd_dcb.operrsta;
        !           870:        if (bp->b_flags & B_FORMAT) {
        !           871:                dk->dk_operrsta = status;
        !           872:                uncache(&vd->vd_dcb.err_code);
        !           873:                /* ecodecnt gets err_code + err_wcnt from the same longword */
        !           874:                dk->dk_ecodecnt = *(long *)&vd->vd_dcb.err_code;
        !           875:                uncache(&vd->vd_dcb.err_trk);
        !           876:                /* erraddr gets error trk/sec/cyl from the same longword */
        !           877:                dk->dk_erraddr = *(long *)&vd->vd_dcb.err_trk;
        !           878:        } else if (status & VDERR_HARD || timedout) {
        !           879:                if (vd->vd_type == VDTYPE_SMDE)
        !           880:                        uncache(&vd->vd_dcb.err_code);
        !           881:                if (status & DCBS_WPT) {
        !           882:                        /*
        !           883:                         * Give up on write locked devices immediately.
        !           884:                         */
        !           885:                        printf("dk%d: write locked\n", vi->ui_unit);
        !           886:                        bp->b_flags |= B_ERROR;
        !           887:                } else if (status & VDERR_RETRY || timedout) {
        !           888:                        if (status & VDERR_CTLR || timedout) {
        !           889:                                vdharderr(timedout ?
        !           890:                                    "controller timeout" : "controller err",
        !           891:                                    vd, bp, &vd->vd_dcb);
        !           892:                                printf("; resetting controller...");
        !           893:                                vdreset_ctlr(vm);
        !           894:                        } else if (status & VDERR_DRIVE) {
        !           895:                                vdharderr("drive err", vd, bp, &vd->vd_dcb);
        !           896:                                printf("; resetting drive...");
        !           897:                                if (!vdreset_drive(vi))
        !           898:                                        dk->dk_state = CLOSED;
        !           899:                        } else
        !           900:                                vdharderr("data err", vd, bp, &vd->vd_dcb);
        !           901:                        /*
        !           902:                         * Retry transfer once, unless reset failed.
        !           903:                         */
        !           904:                        if (!vi->ui_alive || dp->b_errcnt++ >= 1) {
        !           905:                                printf("\n");
        !           906:                                goto hard;
        !           907:                        }
        !           908: 
        !           909:                        printf(" retrying\n");
        !           910:                        vm->um_tab.b_active = 0;        /* force retry */
        !           911:                } else  {
        !           912:                        vdharderr("hard error", vd, bp, &vd->vd_dcb);
        !           913:                        printf("\n");
        !           914:        hard:
        !           915:                        bp->b_flags |= B_ERROR;
        !           916:                }
        !           917:        } else if (status & DCBS_SOFT)
        !           918:                vdsofterr(bp, &vd->vd_dcb);
        !           919: if (vd->vd_wticks > 3) {
        !           920: vd->vd_dcb.err_code = vd->vd_wticks;
        !           921: vdharderr("slow transfer (ecode is sec.)", vd, bp, &vd->vd_dcb);
        !           922: printf("\n");
        !           923: }
        !           924:        vd->vd_wticks = 0;
        !           925:        if (vm->um_tab.b_active) {
        !           926:                vm->um_tab.b_active = 0;
        !           927:                vm->um_tab.b_actf = dp->b_forw;
        !           928:                dp->b_active = 0;
        !           929:                dp->b_errcnt = 0;
        !           930:                dp->b_actf = bp->av_forw;
        !           931:                bp->b_resid = 0;
        !           932:                vbadone(bp, &vd->vd_rbuf);
        !           933:                biodone(bp);
        !           934:                /*
        !           935:                 * If this unit has more work to do,
        !           936:                 * then start it up right away.
        !           937:                 */
        !           938:                if (dp->b_actf)
        !           939:                        vdustart(vi);
        !           940:                else if (dk->dk_openpart == 0)
        !           941:                        wakeup((caddr_t)dk);
        !           942:        }
        !           943:        /*
        !           944:         * If there are devices ready to
        !           945:         * transfer, start the controller.
        !           946:         */
        !           947:        if (vd->vd_flags & VD_WAIT) {
        !           948:                vd->vd_flags &= ~VD_WAIT;
        !           949:                wakeup((caddr_t)vd);
        !           950:        } else if (vm->um_tab.b_actf || vm->um_tab.b_seekf)
        !           951:                vdstart(vm);
        !           952: }
        !           953: 
        !           954: vdharderr(what, vd, bp, dcb)
        !           955:        char *what;
        !           956:        struct vdsoftc *vd;
        !           957:        register struct buf *bp;
        !           958:        register struct dcb *dcb;
        !           959: {
        !           960:        int unit = vdunit(bp->b_dev), status = dcb->operrsta;
        !           961:        register struct disklabel *lp = &dklabel[unit];
        !           962:        int blkdone;
        !           963: 
        !           964:        if (vd->vd_wticks < VDMAXTIME)
        !           965:                status &= ~DONTCARE;
        !           966:        blkdone = ((((dcb->err_cyl & 0xfff) * lp->d_ntracks + dcb->err_trk) *
        !           967:            lp->d_nsectors + dcb->err_sec -
        !           968:            lp->d_partitions[vdpart(bp->b_dev)].p_offset) >>
        !           969:            dksoftc[unit].dk_bshift) - bp->b_blkno;
        !           970:        diskerr(bp, "dk", what, LOG_PRINTF, blkdone, lp);
        !           971:        printf(", status %b", status, VDERRBITS);
        !           972:        if (vd->vd_type == VDTYPE_SMDE)
        !           973:                printf(" ecode %x", dcb->err_code);
        !           974: }
        !           975: 
        !           976: vdsofterr(bp, dcb)
        !           977:        register struct buf *bp;
        !           978:        register struct dcb *dcb;
        !           979: {
        !           980:        int unit = vdunit(bp->b_dev);
        !           981:        struct disklabel *lp = &dklabel[unit];
        !           982:        int status = dcb->operrsta;
        !           983:        int blkdone;
        !           984: 
        !           985:        blkdone = ((((dcb->err_cyl & 0xfff) * lp->d_ntracks + dcb->err_trk) *
        !           986:            lp->d_nsectors + dcb->err_sec -
        !           987:            lp->d_partitions[vdpart(bp->b_dev)].p_offset) >>
        !           988:            dksoftc[unit].dk_bshift) - bp->b_blkno;
        !           989: 
        !           990:        if (status != (DCBS_CCD|DCBS_SOFT|DCBS_ERR|DCBS_DONE)) {
        !           991:                diskerr(bp, "dk", "soft error", LOG_WARNING, blkdone, lp);
        !           992:                addlog(", status %b ecode %x\n", status, VDERRBITS,
        !           993:                    dcb->err_code);
        !           994:        } else {
        !           995:                diskerr(bp, "dk", "soft ecc", LOG_WARNING, blkdone, lp);
        !           996:                addlog("\n");
        !           997:        }
        !           998: }
        !           999: 
        !          1000: vdioctl(dev, cmd, data, flag)
        !          1001:        dev_t dev;
        !          1002:        int cmd;
        !          1003:        caddr_t data;
        !          1004:        int flag;
        !          1005: {
        !          1006:        register int unit = vdunit(dev);
        !          1007:        register struct disklabel *lp = &dklabel[unit];
        !          1008:        register struct dksoftc *dk = &dksoftc[unit];
        !          1009:        int error = 0, vdformat();
        !          1010: 
        !          1011:        switch (cmd) {
        !          1012: 
        !          1013:        case DIOCGDINFO:
        !          1014:                *(struct disklabel *)data = *lp;
        !          1015:                break;
        !          1016: 
        !          1017:        case DIOCGPART:
        !          1018:                ((struct partinfo *)data)->disklab = lp;
        !          1019:                ((struct partinfo *)data)->part =
        !          1020:                    &lp->d_partitions[vdpart(dev)];
        !          1021:                break;
        !          1022: 
        !          1023:        case DIOCSDINFO:
        !          1024:                if ((flag & FWRITE) == 0)
        !          1025:                        error = EBADF;
        !          1026:                else
        !          1027:                        error = setdisklabel(lp, (struct disklabel *)data,
        !          1028:                            (dk->dk_state == OPENRAW) ? 0 : dk->dk_openpart);
        !          1029:                if (error == 0 && dk->dk_state == OPENRAW &&
        !          1030:                    vdreset_drive(vddinfo[unit]))
        !          1031:                        dk->dk_state = OPEN;
        !          1032:                break;
        !          1033: 
        !          1034:        case DIOCWLABEL:
        !          1035:                if ((flag & FWRITE) == 0)
        !          1036:                        error = EBADF;
        !          1037:                else
        !          1038:                        dk->dk_wlabel = *(int *)data;
        !          1039:                break;
        !          1040: 
        !          1041:        case DIOCWDINFO:
        !          1042:                if ((flag & FWRITE) == 0)
        !          1043:                        error = EBADF;
        !          1044:                else if ((error = setdisklabel(lp, (struct disklabel *)data,
        !          1045:                    (dk->dk_state == OPENRAW) ? 0 : dk->dk_openpart)) == 0) {
        !          1046:                        int wlab;
        !          1047: 
        !          1048:                        if (error == 0 && dk->dk_state == OPENRAW &&
        !          1049:                            vdreset_drive(vddinfo[unit]))
        !          1050:                                dk->dk_state = OPEN;
        !          1051:                        /* simulate opening partition 0 so write succeeds */
        !          1052:                        dk->dk_openpart |= (1 << 0);            /* XXX */
        !          1053:                        wlab = dk->dk_wlabel;
        !          1054:                        dk->dk_wlabel = 1;
        !          1055:                        error = writedisklabel(dev, vdstrategy, lp);
        !          1056:                        dk->dk_openpart = dk->dk_copenpart | dk->dk_bopenpart;
        !          1057:                        dk->dk_wlabel = wlab;
        !          1058:                }
        !          1059:                break;
        !          1060: 
        !          1061:        case DIOCWFORMAT:
        !          1062:            {
        !          1063:                register struct format_op *fop;
        !          1064:                struct uio auio;
        !          1065:                struct iovec aiov;
        !          1066: 
        !          1067:                if ((flag & FWRITE) == 0) {
        !          1068:                        error = EBADF;
        !          1069:                        break;
        !          1070:                }
        !          1071:                fop = (struct format_op *)data;
        !          1072:                aiov.iov_base = fop->df_buf;
        !          1073:                aiov.iov_len = fop->df_count;
        !          1074:                auio.uio_iov = &aiov;
        !          1075:                auio.uio_iovcnt = 1;
        !          1076:                auio.uio_resid = fop->df_count;
        !          1077:                auio.uio_segflg = UIO_USERSPACE;
        !          1078:                auio.uio_offset = fop->df_startblk * lp->d_secsize;
        !          1079:                /* This assumes one active format operation per disk... */
        !          1080:                dk->dk_op = fop->dk_op;
        !          1081:                dk->dk_althdr = fop->dk_althdr;
        !          1082:                dk->dk_fmtflags = fop->dk_fmtflags;
        !          1083:                /*
        !          1084:                 * Don't return errors, as the format op won't get copied
        !          1085:                 * out if we return nonzero.  Callers must check the returned
        !          1086:                 * registers and count.
        !          1087:                 */
        !          1088:                error = physio(vdformat, (struct buf *)NULL, dev,
        !          1089:                     B_WRITE, minphys, &auio);
        !          1090:                if (error == EIO)
        !          1091:                        error = 0;
        !          1092:                fop->df_count -= auio.uio_resid;
        !          1093:                /* This assumes one active format operation per disk... */
        !          1094:                fop->dk_operrsta = dk->dk_operrsta;
        !          1095:                fop->dk_ecodecnt = dk->dk_ecodecnt;
        !          1096:                fop->dk_erraddr = dk->dk_erraddr;
        !          1097:                break;
        !          1098:            }
        !          1099: 
        !          1100:        default:
        !          1101:                error = ENOTTY;
        !          1102:                break;
        !          1103:        }
        !          1104:        return (error);
        !          1105: }
        !          1106: 
        !          1107: vdformat(bp)
        !          1108:        struct buf *bp;
        !          1109: {
        !          1110:        bp->b_flags |= B_FORMAT;
        !          1111:        vdstrategy(bp);
        !          1112: }
        !          1113: 
        !          1114: /*
        !          1115:  * Watch for lost interrupts.
        !          1116:  */
        !          1117: vdwatch()
        !          1118: {
        !          1119:        register struct vdsoftc *vd;
        !          1120:        register struct vba_ctlr *vm;
        !          1121:        register int ctlr;
        !          1122:        int s;
        !          1123: 
        !          1124:        timeout(vdwatch, (caddr_t)0, hz);
        !          1125:        for (ctlr = 0; ctlr < NVD; ctlr++) {
        !          1126:                vm = vdminfo[ctlr];
        !          1127:                if (vm == 0 || vm->um_alive == 0)
        !          1128:                        continue;
        !          1129:                vd = &vdsoftc[ctlr];
        !          1130:                s = spl7();
        !          1131:                if (vm->um_tab.b_active && vd->vd_wticks++ >= VDMAXTIME) {
        !          1132:                        printf("vd%d: lost interrupt\n", ctlr);
        !          1133: #ifdef maybe
        !          1134:                        VDABORT((struct vddevice *)vm->um_addr, vd->vd_type);
        !          1135: #endif
        !          1136:                        vdintr(ctlr);
        !          1137:                }
        !          1138:                splx(s);
        !          1139:        }
        !          1140: }
        !          1141: 
        !          1142: #define        DBSIZE  64      /* controller limit with 1K sectors */
        !          1143: /*
        !          1144:  * Crash dump.
        !          1145:  */
        !          1146: vddump(dev)
        !          1147:        dev_t dev;
        !          1148: {
        !          1149:        register struct vba_device *vi;
        !          1150:        register struct vba_ctlr *vm;
        !          1151:        register struct disklabel *lp;
        !          1152:        register struct vdsoftc *vd;
        !          1153:        struct dksoftc *dk;
        !          1154:        int part, unit, num;
        !          1155:        u_long start;
        !          1156: 
        !          1157:        start = 0;
        !          1158:        unit = vdunit(dev);
        !          1159:        if (unit > NDK || (vi = vddinfo[unit]) == 0 || vi->ui_alive == 0)
        !          1160:                return (ENXIO);
        !          1161:        dk = &dksoftc[unit];
        !          1162:        if (dk->dk_state != OPEN && dk->dk_state != OPENRAW &&
        !          1163:            vdinit(vdminor(unit, 0), 0) != 0)
        !          1164:                return (ENXIO);
        !          1165:        lp = &dklabel[unit];
        !          1166:        part = vdpart(dev);
        !          1167:        if (part >= lp->d_npartitions)
        !          1168:                return (ENXIO);
        !          1169:        vm = vi->ui_mi;
        !          1170:        vdreset_ctlr(vm);
        !          1171:        if (dumplo < 0)
        !          1172:                return (EINVAL);
        !          1173:        /*
        !          1174:         * Maxfree is in pages, dumplo is in DEV_BSIZE units.
        !          1175:         */
        !          1176:        num = maxfree * (NBPG / lp->d_secsize);
        !          1177:        dumplo *= DEV_BSIZE / lp->d_secsize;
        !          1178:        if (dumplo + num >= lp->d_partitions[vdpart(dev)].p_size)
        !          1179:                num = lp->d_partitions[vdpart(dev)].p_size - dumplo;
        !          1180:        vd = &vdsoftc[vm->um_ctlr];
        !          1181:        vd->vd_dcb.intflg = DCBINT_NONE;
        !          1182:        vd->vd_dcb.opcode = VDOP_WD;
        !          1183:        vd->vd_dcb.devselect = dk->dk_dcb.devselect;
        !          1184:        vd->vd_dcb.trailcnt = sizeof (struct trrw) / sizeof (long);
        !          1185:        while (num > 0) {
        !          1186:                int nsec, cn, sn, tn;
        !          1187: 
        !          1188:                nsec = MIN(num, DBSIZE);
        !          1189:                sn = dumplo + start / lp->d_secsize;
        !          1190:                cn = (sn + lp->d_partitions[vdpart(dev)].p_offset) /
        !          1191:                    lp->d_secpercyl;
        !          1192:                sn %= lp->d_secpercyl;
        !          1193:                tn = sn / lp->d_nsectors;
        !          1194:                sn %= lp->d_nsectors;
        !          1195:                vd->vd_mdcb.mdcb_head = (struct dcb *)vd->vd_dcbphys;
        !          1196:                vd->vd_dcb.trail.rwtrail.memadr = start;
        !          1197:                vd->vd_dcb.trail.rwtrail.wcount = (nsec * lp->d_secsize) >> 1;
        !          1198:                vd->vd_dcb.trail.rwtrail.disk.cylinder = cn;
        !          1199:                vd->vd_dcb.trail.rwtrail.disk.track = tn;
        !          1200:                vd->vd_dcb.trail.rwtrail.disk.sector = sn;
        !          1201:                vd->vd_dcb.operrsta = 0;
        !          1202:                VDGO(vm->um_addr, vd->vd_mdcbphys, vd->vd_type);
        !          1203:                if (!vdpoll(vm, 5)) {
        !          1204:                        printf(" during dump\n");
        !          1205:                        return (EIO);
        !          1206:                }
        !          1207:                if (vd->vd_dcb.operrsta & VDERR_HARD) {
        !          1208:                        printf("dk%d: hard error, status=%b\n", unit,
        !          1209:                            vd->vd_dcb.operrsta, VDERRBITS);
        !          1210:                        return (EIO);
        !          1211:                }
        !          1212:                start += nsec * lp->d_secsize;
        !          1213:                num -= nsec;
        !          1214:        }
        !          1215:        return (0);
        !          1216: }
        !          1217: 
        !          1218: vdsize(dev)
        !          1219:        dev_t dev;
        !          1220: {
        !          1221:        register int unit = vdunit(dev);
        !          1222:        register struct dksoftc *dk;
        !          1223:        struct vba_device *vi;
        !          1224:        struct disklabel *lp;
        !          1225: 
        !          1226:        if (unit >= NDK || (vi = vddinfo[unit]) == 0 || vi->ui_alive == 0 ||
        !          1227:            (dk = &dksoftc[unit])->dk_state != OPEN)
        !          1228:                return (-1);
        !          1229:        lp = &dklabel[unit];
        !          1230: #ifdef SECSIZE
        !          1231:        return ((int)lp->d_partitions[vdpart(dev)].p_size);
        !          1232: #else SECSIZE
        !          1233:        return ((int)lp->d_partitions[vdpart(dev)].p_size >> dk->dk_bshift);
        !          1234: #endif SECSIZE
        !          1235: }
        !          1236: 
        !          1237: /*
        !          1238:  * Initialize controller.
        !          1239:  */
        !          1240: vdinit_ctlr(vm, vd)
        !          1241:        struct vba_ctlr *vm;
        !          1242:        struct vdsoftc *vd;
        !          1243: {
        !          1244:        register struct vddevice *vdaddr = (struct vddevice *)vm->um_addr;
        !          1245: 
        !          1246:        if (vd->vd_type == VDTYPE_SMDE) {
        !          1247:                vdaddr->vdcsr = 0;
        !          1248:                vdaddr->vdtcf_mdcb = AM_ENPDA;
        !          1249:                vdaddr->vdtcf_dcb = AM_ENPDA;
        !          1250:                vdaddr->vdtcf_trail = AM_ENPDA;
        !          1251:                vdaddr->vdtcf_data = AM_ENPDA;
        !          1252:                vdaddr->vdccf = CCF_SEN | CCF_DIU | CCF_STS | CCF_RFE |
        !          1253:                    XMD_32BIT | BSZ_16WRD |
        !          1254:                    CCF_ENP | CCF_EPE | CCF_EDE | CCF_ECE | CCF_ERR;
        !          1255:        }
        !          1256:        if (!vdcmd(vm, VDOP_INIT, 10, 0) || !vdcmd(vm, VDOP_DIAG, 10, 0)) {
        !          1257:                printf("vd%d: %s cmd failed\n", vm->um_ctlr,
        !          1258:                    vd->vd_dcb.opcode == VDOP_INIT ? "init" : "diag");
        !          1259:                return (0);
        !          1260:        }
        !          1261:        vd->vd_secsize = vdaddr->vdsecsize << 1;
        !          1262:        return (1);
        !          1263: }
        !          1264: 
        !          1265: /*
        !          1266:  * Perform a controller reset.
        !          1267:  */
        !          1268: vdreset_ctlr(vm)
        !          1269:        register struct vba_ctlr *vm;
        !          1270: {
        !          1271:        register struct vddevice *vdaddr = (struct vddevice *)vm->um_addr;
        !          1272:        register struct vdsoftc *vd = &vdsoftc[vm->um_ctlr];
        !          1273:        register int unit;
        !          1274:        struct vba_device *vi;
        !          1275:        
        !          1276:        VDRESET(vdaddr, vd->vd_type);
        !          1277:        if (vdinit_ctlr(vm, vd) == 0)
        !          1278:                return;
        !          1279:        for (unit = 0; unit < NDK; unit++)
        !          1280:                if (vi = vddinfo[unit] && vi->ui_mi == vm && vi->ui_alive)
        !          1281:                        (void) vdreset_drive(vi);
        !          1282: }
        !          1283: 
        !          1284: vdreset_drive(vi)
        !          1285:        register struct vba_device *vi;
        !          1286: {
        !          1287:        register struct disklabel *lp = &dklabel[vi->ui_unit];
        !          1288:        struct vba_ctlr *vm = vdminfo[vi->ui_ctlr];
        !          1289:        struct vddevice *vdaddr = (struct vddevice *)vm->um_addr;
        !          1290:        register struct vdsoftc *vd = &vdsoftc[vi->ui_ctlr];
        !          1291:        register struct dksoftc *dk = &dksoftc[vi->ui_unit];
        !          1292:        int config_status, config_ecode, saw_drive = 0;
        !          1293: 
        !          1294: #ifdef notdef
        !          1295:        /*
        !          1296:         * check for ESDI distribution panel already configured,
        !          1297:         * e.g. on boot drive, or if PROBE on controller actually
        !          1298:         * worked.  Status will be zero if drive hasn't
        !          1299:         * been probed yet.
        !          1300:         */
        !          1301: #if STA_ESDI != 0
        !          1302:        if ((vdaddr->vdstatus[vi->ui_slave] & STA_TYPE) == STA_ESDI)
        !          1303:                lp->d_devflags |= VD_ESDI;
        !          1304: #endif
        !          1305: #endif
        !          1306: top:
        !          1307:        vd->vd_dcb.opcode = VDOP_CONFIG;                /* command */
        !          1308:        vd->vd_dcb.intflg = DCBINT_NONE;
        !          1309:        vd->vd_dcb.nxtdcb = (struct dcb *)0;    /* end of chain */
        !          1310:        vd->vd_dcb.operrsta = 0;
        !          1311:        vd->vd_dcb.devselect = vi->ui_slave | lp->d_devflags;
        !          1312:        vd->vd_dcb.trail.rstrail.ncyl = lp->d_ncylinders;
        !          1313:        vd->vd_dcb.trail.rstrail.nsurfaces = lp->d_ntracks;
        !          1314:        if (vd->vd_type == VDTYPE_SMDE) {
        !          1315:                vd->vd_dcb.trailcnt = sizeof (struct treset) / sizeof (long);
        !          1316:                vd->vd_dcb.trail.rstrail.nsectors = lp->d_nsectors;
        !          1317:                vd->vd_dcb.trail.rstrail.slip_sec = lp->d_sparespertrack;
        !          1318:                vd->vd_dcb.trail.rstrail.recovery =
        !          1319:                    (lp->d_flags & D_REMOVABLE) ? VDRF_NORMAL :
        !          1320:                    (VDRF_NORMAL &~ (VDRF_OSP|VDRF_OSM));
        !          1321:        } else
        !          1322:                vd->vd_dcb.trailcnt = 2;                /* XXX */
        !          1323:        vd->vd_mdcb.mdcb_head = (struct dcb *)vd->vd_dcbphys;
        !          1324:        vd->vd_mdcb.mdcb_status = 0;
        !          1325:        VDGO(vdaddr, vd->vd_mdcbphys, vd->vd_type);
        !          1326:        if (!vdpoll(vm, 5)) {
        !          1327:                printf(" during config\n");
        !          1328:                return (0);
        !          1329:        }
        !          1330:        config_status = vd->vd_dcb.operrsta;
        !          1331:        config_ecode = (u_char)vd->vd_dcb.err_code;
        !          1332:        if (config_status & VDERR_HARD) {
        !          1333:                if (vd->vd_type == VDTYPE_SMDE) {
        !          1334:                        /*
        !          1335:                         * If drive status was updated successfully,
        !          1336:                         * STA_US (unit selected) should be set
        !          1337:                         * if the drive is attached and powered up.
        !          1338:                         * (But only if we've guessed right on SMD
        !          1339:                         * vs. ESDI; if that flag is wrong, we won't
        !          1340:                         * see the drive.)  If we don't see STA_US
        !          1341:                         * with either SMD or ESDI set for the unit,
        !          1342:                         * we assume that the drive doesn't exist,
        !          1343:                         * and don't wait for it to spin up.
        !          1344:                         */
        !          1345:                        (void) vdcmd(vm, VDOP_STATUS, 5, vi->ui_slave);
        !          1346:                        uncache(&vdaddr->vdstatus[vi->ui_slave]);
        !          1347:                        if (vdaddr->vdstatus[vi->ui_slave] & STA_US)
        !          1348:                                saw_drive = 1;
        !          1349:                        else if (lp->d_devflags == 0) {
        !          1350:                                lp->d_devflags = VD_ESDI;
        !          1351:                                goto top;
        !          1352:                        }
        !          1353:                } else
        !          1354:                        saw_drive = 1;
        !          1355:                if ((config_status & (DCBS_OCYL|DCBS_NRDY)) == 0)
        !          1356:                        printf("dk%d: config error %b ecode %x\n", vi->ui_unit,
        !          1357:                           config_status, VDERRBITS, config_ecode);
        !          1358:                else if ((vd->vd_flags & VD_STARTED) == 0 && saw_drive) {
        !          1359:                        int started;
        !          1360: 
        !          1361:                        printf(" starting drives, wait ... ");
        !          1362:                        vd->vd_flags |= VD_STARTED;
        !          1363:                        started = (vdcmd(vm, VDOP_START, 10) == 1);
        !          1364:                        DELAY(62000000);
        !          1365:                        printf("done\n");
        !          1366:                        lp->d_devflags = 0;
        !          1367:                        if (started)
        !          1368:                                goto top;
        !          1369:                }
        !          1370:                return (0);
        !          1371:        }
        !          1372:        dk->dk_dcb.devselect |= lp->d_devflags;
        !          1373:        return (1);
        !          1374: }
        !          1375: 
        !          1376: /*
        !          1377:  * Perform a command w/o trailer.
        !          1378:  */
        !          1379: vdcmd(vm, cmd, t, slave)
        !          1380:        register struct vba_ctlr *vm;
        !          1381: {
        !          1382:        register struct vdsoftc *vd = &vdsoftc[vm->um_ctlr];
        !          1383: 
        !          1384:        vd->vd_dcb.opcode = cmd;                /* command */
        !          1385:        vd->vd_dcb.intflg = DCBINT_NONE;
        !          1386:        vd->vd_dcb.nxtdcb = (struct dcb *)0;    /* end of chain */
        !          1387:        vd->vd_dcb.operrsta = 0;
        !          1388:        vd->vd_dcb.devselect = slave;
        !          1389:        vd->vd_dcb.trailcnt = 0;
        !          1390:        vd->vd_mdcb.mdcb_head = (struct dcb *)vd->vd_dcbphys;
        !          1391:        vd->vd_mdcb.mdcb_status = 0;
        !          1392:        VDGO(vm->um_addr, vd->vd_mdcbphys, vd->vd_type);
        !          1393:        if (!vdpoll(vm, t)) {
        !          1394:                printf(" during init\n");
        !          1395:                return (0);
        !          1396:        }
        !          1397:        return ((vd->vd_dcb.operrsta&VDERR_HARD) == 0);
        !          1398: }
        !          1399: 
        !          1400: /*
        !          1401:  * Poll controller until operation
        !          1402:  * completes or timeout expires.
        !          1403:  */
        !          1404: vdpoll(vm, t)
        !          1405:        register struct vba_ctlr *vm;
        !          1406:        register int t;
        !          1407: {
        !          1408:        register struct vdsoftc *vd = &vdsoftc[vm->um_ctlr];
        !          1409:        register struct vddevice *vdaddr = (struct vddevice *)vm->um_addr;
        !          1410: 
        !          1411:        t *= 1000;
        !          1412:        for (;;) {
        !          1413:                uncache(&vd->vd_dcb.operrsta);
        !          1414:                if (vd->vd_dcb.operrsta & (DCBS_DONE|DCBS_ABORT))
        !          1415:                        break;
        !          1416:                if (--t <= 0) {
        !          1417:                        printf("vd%d: controller timeout", vm->um_ctlr);
        !          1418:                        VDABORT(vdaddr, vd->vd_type);
        !          1419:                        return (0);
        !          1420:                }
        !          1421:                DELAY(1000);
        !          1422:        }
        !          1423:        if (vd->vd_type == VDTYPE_SMDE) {
        !          1424:                do {
        !          1425:                        DELAY(50);
        !          1426:                        uncache(&vdaddr->vdcsr);
        !          1427:                } while (vdaddr->vdcsr & CS_GO);
        !          1428:                DELAY(300);
        !          1429:                uncache(&vd->vd_dcb.err_code);
        !          1430:        }
        !          1431:        DELAY(200);
        !          1432:        uncache(&vd->vd_dcb.operrsta);
        !          1433:        return (1);
        !          1434: }
        !          1435: 
        !          1436: #ifdef COMPAT_42
        !          1437: struct vdst {
        !          1438:        int     nsec;           /* sectors/track */
        !          1439:        int     ntrack;         /* tracks/cylinder */
        !          1440:        int     ncyl;           /* cylinders */
        !          1441:        int     secsize;        /* sector size */
        !          1442:        char    *name;          /* type name */
        !          1443:        struct {
        !          1444:                int     off;    /* partition offset in sectors */
        !          1445:                int     size;   /* partition size in sectors */
        !          1446:        } parts[8];
        !          1447: } vdst[] = {
        !          1448:        { 66, 23, 850, 512, "NEC 800",
        !          1449:                {0,      1290300},      /* a cyl   0 - 849 */
        !          1450:        },
        !          1451:        { 64, 20, 842, 512, "2361a",
        !          1452:                {0,      61440},        /* a cyl   0 - 47 */
        !          1453:                {61440,  67840},        /* b cyl  48 - 100 */
        !          1454:                {129280, 942080},       /* c cyl 101 - 836 */
        !          1455:                {0,      1071360},      /* d cyl   0 - 836 */
        !          1456:                {449280, 311040},       /* e cyl 351 - 593 */
        !          1457:                {760320, 311040},       /* f cyl 594 - 836 */
        !          1458:                {449280, 622080},       /* g cyl 351 - 836 */
        !          1459:                {129280, 320000}        /* h cyl 101 - 350 */
        !          1460:        },
        !          1461:        { 48, 24, 711, 512, "xsd",
        !          1462:                {0,      61056},        /* a cyl   0 - 52 */
        !          1463:                {61056,  61056},        /* b cyl  53 - 105 */
        !          1464:                {122112, 691200},       /* c cyl 106 - 705 */
        !          1465:                {237312, 576000},       /* d cyl 206 - 705 */
        !          1466:                {352512, 460800},       /* e cyl 306 - 705 */
        !          1467:                {467712, 345600},       /* f cyl 406 - 705 */
        !          1468:                {582912, 230400},       /* g cyl 506 - 705 */
        !          1469:                {698112, 115200}        /* h cyl 606 - 705 */
        !          1470:        },
        !          1471:        { 44, 20, 842, 512, "eagle",
        !          1472:                {0,      52800},        /* egl0a cyl   0 - 59 */
        !          1473:                {52800,  66000},        /* egl0b cyl  60 - 134 */
        !          1474:                {118800, 617760},       /* egl0c cyl 135 - 836 */
        !          1475:                {736560, 4400},         /* egl0d cyl 837 - 841 */
        !          1476:                {0,      736560},       /* egl0e cyl   0 - 836 */
        !          1477:                {0,      740960},       /* egl0f cyl   0 - 841 */
        !          1478:                {118800, 310640},       /* egl0g cyl 135 - 487 */
        !          1479:                {429440, 307120}        /* egl0h cyl 488 - 836 */
        !          1480:        },
        !          1481:        { 64, 10, 823, 512, "fuj",
        !          1482:                {0,      38400},        /* fuj0a cyl   0 - 59 */
        !          1483:                {38400,  48000},        /* fuj0b cyl  60 - 134 */
        !          1484:                {86400,  437120},       /* fuj0c cyl 135 - 817 */
        !          1485:                {159360, 364160},       /* fuj0d cyl 249 - 817 */
        !          1486:                {232320, 291200},       /* fuj0e cyl 363 - 817 */
        !          1487:                {305280, 218240},       /* fuj0f cyl 477 - 817 */
        !          1488:                {378240, 145280},       /* fuj0g cyl 591 - 817 */
        !          1489:                {451200, 72320}         /* fug0h cyl 705 - 817 */
        !          1490:        },
        !          1491:        { 32, 24, 711, 512, "xfd",
        !          1492:                { 0,     40704 },       /* a cyl   0 - 52 */
        !          1493:                { 40704, 40704 },       /* b cyl  53 - 105 */
        !          1494:                { 81408, 460800 },      /* c cyl 106 - 705 */
        !          1495:                { 0,     81408 },       /* d cyl 709 - 710 (a & b) */
        !          1496:                { 0,     542208 },      /* e cyl   0 - 705 */
        !          1497:                { 40704, 501504 },      /* f cyl  53 - 705 (b & c) */
        !          1498:                { 81408, 230400 },      /* g cyl 106 - 405 (1/2 of c) */
        !          1499:                { 311808,230400 }       /* h cyl 406 - 705 (1/2 of c) */
        !          1500:        },
        !          1501:        { 32, 19, 823, 512, "smd",
        !          1502:                {0,      40128},        /* a cyl   0-65 */
        !          1503:                {40128,  27360},        /* b cyl  66-110 */
        !          1504:                {67488,  429856},       /* c cyl 111-817 */
        !          1505:                {139232, 358112},       /* d cyl 229 - 817 */
        !          1506:                {210976, 286368},       /* e cyl 347 - 817 */
        !          1507:                {282720, 214624},       /* f cyl 465 - 817 */
        !          1508:                {354464, 142880},       /* g cyl 583 - 817 */
        !          1509:                {426208, 71136}         /* h cyl 701 - 817 */
        !          1510:        },
        !          1511:        { 18, 15, 1224, 1024, "mxd",
        !          1512:                {0,      21600},        /* a cyl   0-79 */
        !          1513:                {21600,  22410},        /* b cyl  80-162 */
        !          1514:                {44010,  285120},       /* c cyl 163-1217 */
        !          1515: #ifdef notyet
        !          1516:                {x, 237600},    /* d cyl y - 1217 */
        !          1517:                {x, 190080},    /* e cyl y - 1217 */
        !          1518:                {x, 142560},    /* f cyl y - 1217 */
        !          1519:                {x, 95040},     /* g cyl y - 1217 */
        !          1520:                {x, 47520}              /* h cyl 701 - 817 */
        !          1521: #endif
        !          1522:        },
        !          1523:        { 32, 10, 823, 512, "fsd",
        !          1524:                {0,      19200},        /* a cyl   0 -  59 */
        !          1525:                {19200,  24000},        /* b cyl  60 - 134 */
        !          1526:                {43200,  218560},       /* c cyl 135 - 817 */
        !          1527:        }
        !          1528: };
        !          1529: #define        NVDST   (sizeof (vdst) / sizeof (vdst[0]))
        !          1530: 
        !          1531: /*
        !          1532:  * Construct a label for an unlabeled pack.  We
        !          1533:  * deduce the drive type by reading from the last
        !          1534:  * track on successively smaller drives until we
        !          1535:  * don't get an error.
        !          1536:  */
        !          1537: vdmaptype(vi, lp)
        !          1538:        register struct vba_device *vi;
        !          1539:        register struct disklabel *lp;
        !          1540: {
        !          1541:        register struct vdsoftc *vd;
        !          1542:        register struct vdst *p;
        !          1543:        struct vba_ctlr *vm = vi->ui_mi;
        !          1544:        int i;
        !          1545: 
        !          1546:        vd = &vdsoftc[vi->ui_ctlr];
        !          1547:        for (p = vdst; p < &vdst[NVDST]; p++) {
        !          1548:                if (vd->vd_type == VDTYPE_VDDC && p->nsec != 32)
        !          1549:                        continue;
        !          1550:                lp->d_nsectors = p->nsec;
        !          1551:                lp->d_ntracks = p->ntrack;
        !          1552:                lp->d_ncylinders = p->ncyl;
        !          1553:                lp->d_secsize = p->secsize;
        !          1554:                DELAY(100000);
        !          1555:                if (!vdreset_drive(vi))
        !          1556:                        return (0);
        !          1557:                DELAY(100000);
        !          1558:                vd->vd_dcb.opcode = VDOP_RD;
        !          1559:                vd->vd_dcb.intflg = DCBINT_NONE;
        !          1560:                vd->vd_dcb.nxtdcb = (struct dcb *)0;    /* end of chain */
        !          1561:                vd->vd_dcb.devselect = dksoftc[vi->ui_unit].dk_dcb.devselect;
        !          1562:                vd->vd_dcb.trailcnt = sizeof (struct trrw) / sizeof (long);
        !          1563:                vd->vd_dcb.trail.rwtrail.memadr =
        !          1564:                    vtoph((struct proc *)0, (unsigned)vd->vd_rbuf.vb_rawbuf);
        !          1565:                vd->vd_dcb.trail.rwtrail.wcount = lp->d_secsize / sizeof(short);
        !          1566:                vd->vd_dcb.operrsta = 0;
        !          1567:                vd->vd_dcb.trail.rwtrail.disk.cylinder = p->ncyl - 2;
        !          1568:                vd->vd_dcb.trail.rwtrail.disk.track = p->ntrack - 1;
        !          1569:                vd->vd_dcb.trail.rwtrail.disk.sector = p->nsec - 1;
        !          1570:                vd->vd_mdcb.mdcb_head = (struct dcb *)vd->vd_dcbphys;
        !          1571:                vd->vd_mdcb.mdcb_status = 0;
        !          1572:                VDGO(vm->um_addr, vd->vd_mdcbphys, vd->vd_type);
        !          1573:                if (!vdpoll(vm, 60))
        !          1574:                        printf(" during probe\n");
        !          1575:                if ((vd->vd_dcb.operrsta & VDERR_HARD) == 0)
        !          1576:                        break;
        !          1577:        }
        !          1578:        if (p >= &vdst[NVDST])
        !          1579:                return (0);
        !          1580: 
        !          1581:        for (i = 0; i < 8; i++) {
        !          1582:                lp->d_partitions[i].p_offset = p->parts[i].off;
        !          1583:                lp->d_partitions[i].p_size = p->parts[i].size;
        !          1584:        }
        !          1585:        lp->d_npartitions = 8;
        !          1586:        lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks;
        !          1587:        bcopy(p->name, lp->d_typename, 4);
        !          1588:        return (1);
        !          1589: }
        !          1590: #endif COMPAT_42
        !          1591: #endif

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.