Annotation of 43BSDTahoe/sys/tahoevba/vd.c, revision 1.1

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

unix.superglobalmegacorp.com

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