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

unix.superglobalmegacorp.com

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