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

unix.superglobalmegacorp.com

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