Annotation of 43BSDReno/sys/tahoevba/vd.c, revision 1.1.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.