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

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1988 The Regents of the University of California.
        !             3:  * All rights reserved.
        !             4:  *
        !             5:  * This code is derived from software contributed to Berkeley by
        !             6:  * Harris Corp.
        !             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:  *     @(#)hd.c        7.12 (Berkeley) 12/16/90
        !            37:  */
        !            38: 
        !            39: #include "hd.h"
        !            40: 
        !            41: #if NHD > 0
        !            42: #include "sys/param.h"
        !            43: #include "sys/buf.h"
        !            44: #include "sys/conf.h"
        !            45: #include "sys/dkstat.h"
        !            46: #include "sys/disklabel.h"
        !            47: #include "sys/file.h"
        !            48: #include "sys/systm.h"
        !            49: #include "sys/vmmac.h"
        !            50: #include "sys/time.h"
        !            51: #include "sys/proc.h"
        !            52: #include "sys/uio.h"
        !            53: #include "sys/syslog.h"
        !            54: #include "sys/kernel.h"
        !            55: #include "sys/ioctl.h"
        !            56: #include "sys/stat.h"
        !            57: #include "sys/errno.h"
        !            58: 
        !            59: #include "../include/cpu.h"
        !            60: #include "../include/mtpr.h"
        !            61: 
        !            62: #include "../vba/vbavar.h"
        !            63: #include "../vba/hdreg.h"
        !            64: 
        !            65: #define        b_cylin b_resid
        !            66: 
        !            67: #define        hdunit(dev)             (minor(dev)>>3)
        !            68: #define        hdpart(dev)             (minor(dev)&0x07)
        !            69: #define        hdminor(unit, part)     (((unit)<<3)|(part))
        !            70: 
        !            71: struct vba_ctlr *hdcminfo[NHDC];
        !            72: struct vba_device *hddinfo[NHD];
        !            73: int hdcprobe(), hdslave(), hdattach(), hddgo(), hdstrategy();
        !            74: long hdstd[] = { 0 };
        !            75: struct vba_driver hdcdriver =
        !            76:     { hdcprobe, hdslave, hdattach, hddgo, hdstd, "hd", hddinfo, "hdc", hdcminfo };
        !            77: 
        !            78: /*
        !            79:  * Per-controller state.
        !            80:  */
        !            81: struct hdcsoftc {
        !            82:        u_short hdc_flags;
        !            83: #define        HDC_INIT        0x01    /* controller initialized */
        !            84: #define        HDC_STARTED     0x02    /* start command issued */
        !            85: #define        HDC_LOCKED      0x04    /* locked for direct controller access */
        !            86: #define        HDC_WAIT        0x08    /* someone needs direct controller access */
        !            87:        u_short hdc_wticks;             /* timeout */
        !            88:        struct master_mcb *hdc_mcbp;    /* address of controller mcb */
        !            89:        struct registers *hdc_reg;      /* base address of i/o regs */
        !            90:        struct vb_buf hdc_rbuf;         /* vba resources */
        !            91:        struct master_mcb hdc_mcb;      /* controller mcb */
        !            92: } hdcsoftc[NHDC];
        !            93: 
        !            94: #define        HDCMAXTIME      20              /* max time for operation, sec. */
        !            95: #define        HDCINTERRUPT    0xf0            /* interrupt vector */
        !            96: 
        !            97: /*
        !            98:  * Per-drive state; probably everything should be "hd_", not "dk_",
        !            99:  * but it's not worth it, and dk is a better mnemonic for disk anyway.
        !           100:  */
        !           101: struct dksoftc {
        !           102: #ifdef COMPAT_42
        !           103:        u_short dk_def_cyl;     /* definition track cylinder address */
        !           104: #endif
        !           105:        int     dk_state;       /* open fsm */
        !           106:        u_short dk_bshift;      /* shift for * (DEV_BSIZE / sectorsize) XXX */
        !           107:        int     dk_wlabel;      /* if label sector is writeable */
        !           108:        u_long  dk_copenpart;   /* character units open on this drive */
        !           109:        u_long  dk_bopenpart;   /* block units open on this drive */
        !           110:        u_long  dk_openpart;    /* all units open on this drive */
        !           111:        int     dk_unit;        /* unit# */
        !           112:        int     dk_ctlr;        /* controller# */
        !           113:        int     dk_format;      /* if format program is using disk */
        !           114:        struct buf dk_utab;             /* i/o queue header */
        !           115:        struct disklabel dk_label;      /* disklabel for this disk */
        !           116:        struct mcb dk_mcb;              /* disk mcb */
        !           117: } dksoftc[NHD];
        !           118: 
        !           119: /*
        !           120:  * Drive states.  Used during steps of open/initialization.
        !           121:  * States < OPEN (> 0) are transient, during an open operation.
        !           122:  * OPENRAW is used for unlabeled disks, to allow format operations.
        !           123:  */
        !           124: #define        CLOSED          0               /* disk is closed */
        !           125: #define        WANTOPEN        1               /* open requested, not started */
        !           126: #define        WANTOPENRAW     2               /* open requested, no label */
        !           127: #define        RDLABEL         3               /* reading pack label */
        !           128: #define        OPEN            4               /* intialized and ready */
        !           129: #define        OPENRAW         5               /* open, no label */
        !           130: 
        !           131: int hdcwstart, hdcwatch();
        !           132: 
        !           133: /* see if the controller is really there, if so, init it. */
        !           134: /* ARGSUSED */
        !           135: hdcprobe(reg, vm)
        !           136:        caddr_t reg;
        !           137:        /* register */ struct vba_ctlr *vm;
        !           138: {
        !           139:        register int br, cvec;          /* must be r12, r11 */
        !           140:        register struct hdcsoftc *hdc;
        !           141:        static struct module_id id;
        !           142:        struct pte *dummypte;
        !           143:        caddr_t putl;
        !           144: 
        !           145:        /* initialize the hdc controller structure. */
        !           146:        hdc = &hdcsoftc[vm->um_ctlr];
        !           147:        if (!vbmemalloc(1, reg, &dummypte, &putl)) {
        !           148:                printf("hdc%d: vbmemalloc failed.\n", vm->um_ctlr);
        !           149:                return(0);
        !           150:        }
        !           151:        hdc->hdc_reg = (struct registers *)putl;
        !           152: 
        !           153:        /*
        !           154:         * try and ping the MID register; side effect of wbadaddr is to read
        !           155:         * the module id; the controller is bad if it's not an hdc, the hdc's
        !           156:         * writeable control store is not loaded, or the hdc failed the
        !           157:         * functional integrity test;
        !           158:         */
        !           159:        if (wbadaddr(&hdc->hdc_reg->module_id, 4,
        !           160:            vtoph((struct process *)NULL, &id)))
        !           161:                return(0);
        !           162:        DELAY(10000);
        !           163:        mtpr(PADC, 0);
        !           164:        if (id.module_id != (u_char)HDC_MID) {
        !           165:                printf("hdc%d: bad module id; id = %x.\n",
        !           166:                    vm->um_ctlr, id.module_id);
        !           167:                return(0);
        !           168:        }
        !           169:        if (id.code_rev == (u_char)0xff) {
        !           170:                printf("hdc%d: micro-code not loaded.\n", vm->um_ctlr);
        !           171:                return(0);
        !           172:        }
        !           173:        if (id.fit != (u_char)0xff) {
        !           174:                printf("hdc%d: FIT test failed.\n", vm->um_ctlr);
        !           175:                return(0);
        !           176:        }
        !           177: 
        !           178:        /* reset that pup; flag as inited */
        !           179:        hdc->hdc_reg->soft_reset = 0;
        !           180:        DELAY(1000000);
        !           181:        hdc->hdc_flags |= HDC_INIT;
        !           182: 
        !           183:        /* allocate page tables and i/o buffer. */
        !           184:        if (!vbainit(&hdc->hdc_rbuf, MAXPHYS, VB_32BIT|VB_SCATTER)) {
        !           185:                printf("hdc%d: vbainit failed\n", vm->um_ctlr);
        !           186:                return (0);
        !           187:        }
        !           188: 
        !           189:        /* set pointer to master control block */
        !           190:        hdc->hdc_mcbp =
        !           191:            (struct master_mcb *)vtoph((struct proc *)NULL, &hdc->hdc_mcb);
        !           192: 
        !           193:        br = 0x17, cvec = HDCINTERRUPT + vm->um_ctlr;           /* XXX */
        !           194:        return(sizeof(struct registers));
        !           195: }
        !           196: 
        !           197: /* ARGSUSED */
        !           198: hdslave(vi, vdaddr)
        !           199:        struct vba_device *vi;
        !           200:        struct vddevice *vdaddr;
        !           201: {
        !           202:        register struct mcb *mcb;
        !           203:        register struct disklabel *lp;
        !           204:        register struct dksoftc *dk;
        !           205:        static struct status status;
        !           206: 
        !           207:        dk = &dksoftc[vi->ui_unit];
        !           208:        dk->dk_unit = vi->ui_unit;
        !           209:        dk->dk_ctlr = vi->ui_ctlr;
        !           210: 
        !           211:        mcb = &dk->dk_mcb;
        !           212:        mcb->command = HCMD_STATUS;
        !           213:        mcb->chain[0].wcount = sizeof(struct status) / sizeof(long);
        !           214:        mcb->chain[0].memadr  = (u_long)vtoph((struct process *)0, &status);
        !           215:        if (hdimcb(dk)) {
        !           216:                printf(" (no status)\n");
        !           217:                return(0);
        !           218:        }
        !           219: 
        !           220:        /*
        !           221:         * Report the drive down if anything in the drive status looks bad.
        !           222:         * If the drive is offline and it is not on cylinder, then the drive
        !           223:         * is not there.  If there is a fault condition, the hdc will try to
        !           224:         * clear it when we read the disklabel information.
        !           225:         */
        !           226:        if (!(status.drs&DRS_ONLINE)) {
        !           227:                if (status.drs&DRS_ON_CYLINDER)
        !           228:                        printf(" (not online)\n");
        !           229:                return(0);
        !           230:        }
        !           231:        if (status.drs&DRS_FAULT)
        !           232:                printf(" (clearing fault)");
        !           233: 
        !           234:        lp = &dk->dk_label;
        !           235: #ifdef RAW_SIZE
        !           236:        lp->d_secsize = status.bytes_per_sec;
        !           237: #else
        !           238:        lp->d_secsize = 512;
        !           239: #endif
        !           240:        lp->d_nsectors = status.max_sector + 1;
        !           241:        lp->d_ntracks = status.max_head + 1;
        !           242:        lp->d_ncylinders = status.max_cyl + 1;
        !           243:        lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
        !           244:        lp->d_npartitions = 1;
        !           245:        lp->d_partitions[0].p_offset = 0;
        !           246:        lp->d_partitions[0].p_size = LABELSECTOR + 1;
        !           247:        lp->d_rpm = status.rpm;
        !           248:        lp->d_typename[0] = 'h';
        !           249:        lp->d_typename[1] = 'd';
        !           250:        lp->d_typename[2] = '\0';
        !           251: #ifdef COMPAT_42
        !           252:        dk->dk_def_cyl = status.def_cyl;
        !           253: #endif
        !           254:        return(1);
        !           255: }
        !           256: 
        !           257: hdattach(vi)
        !           258:        register struct vba_device *vi;
        !           259: {
        !           260:        register struct dksoftc *dk;
        !           261:        register struct disklabel *lp;
        !           262:        register int unit;
        !           263: 
        !           264:        unit = vi->ui_unit;
        !           265:        if (hdinit(hdminor(unit, 0), 0)) {
        !           266:                printf(": unknown drive type");
        !           267:                return;
        !           268:        }
        !           269:        dk = &dksoftc[unit];
        !           270:        lp = &dk->dk_label;
        !           271:        hd_setsecsize(dk, lp);
        !           272:        if (dk->dk_state == OPEN)
        !           273:                printf(": %s <secsize %d, ntrak %d, ncyl %d, nsec %d>",
        !           274:                    lp->d_typename, lp->d_secsize, lp->d_ntracks,
        !           275:                    lp->d_ncylinders, lp->d_nsectors);
        !           276: 
        !           277:        /*
        !           278:         * (60 / rpm) / (sectors per track * (bytes per sector / 2))
        !           279:         */
        !           280:        if (vi->ui_dk >= 0)
        !           281:                dk_wpms[vi->ui_dk] =
        !           282:                    (lp->d_rpm * lp->d_nsectors * lp->d_secsize) / 120;
        !           283: #ifdef notyet
        !           284:        addswap(makedev(HDMAJOR, hdminor(unit, 0)), lp);
        !           285: #endif
        !           286: }
        !           287: 
        !           288: hdopen(dev, flags, fmt)
        !           289:        dev_t dev;
        !           290:        int flags, fmt;
        !           291: {
        !           292:        register struct disklabel *lp;
        !           293:        register struct dksoftc *dk;
        !           294:        register struct partition *pp;
        !           295:        register int unit;
        !           296:        struct vba_device *vi;
        !           297:        int s, error, part = hdpart(dev), mask = 1 << part;
        !           298:        daddr_t start, end;
        !           299: 
        !           300:        unit = hdunit(dev);
        !           301:        if (unit >= NHD || (vi = hddinfo[unit]) == 0 || vi->ui_alive == 0)
        !           302:                return(ENXIO);
        !           303:        dk = &dksoftc[unit];
        !           304:        lp = &dk->dk_label;
        !           305:        s = spl7();
        !           306:        while (dk->dk_state != OPEN && dk->dk_state != OPENRAW &&
        !           307:            dk->dk_state != CLOSED)
        !           308:                if (error = tsleep((caddr_t)dk, (PZERO+1) | PCATCH,
        !           309:                    devopn, 0)) {
        !           310:                        splx(s);
        !           311:                        return (error);
        !           312:                }
        !           313:        splx(s);
        !           314:        if (dk->dk_state != OPEN && dk->dk_state != OPENRAW)
        !           315:                if (error = hdinit(dev, flags))
        !           316:                        return(error);
        !           317: 
        !           318:        if (hdcwstart == 0) {
        !           319:                timeout(hdcwatch, (caddr_t)0, hz);
        !           320:                hdcwstart++;
        !           321:        }
        !           322:        /*
        !           323:         * Warn if a partion is opened that overlaps another partition
        !           324:         * which is open unless one is the "raw" partition (whole disk).
        !           325:         */
        !           326: #define        RAWPART         8               /* 'x' partition */     /* XXX */
        !           327:        if ((dk->dk_openpart & mask) == 0 && part != RAWPART) {
        !           328:                pp = &lp->d_partitions[part];
        !           329:                start = pp->p_offset;
        !           330:                end = pp->p_offset + pp->p_size;
        !           331:                for (pp = lp->d_partitions;
        !           332:                     pp < &lp->d_partitions[lp->d_npartitions]; pp++) {
        !           333:                        if (pp->p_offset + pp->p_size <= start ||
        !           334:                            pp->p_offset >= end)
        !           335:                                continue;
        !           336:                        if (pp - lp->d_partitions == RAWPART)
        !           337:                                continue;
        !           338:                        if (dk->dk_openpart & (1 << (pp - lp->d_partitions)))
        !           339:                                log(LOG_WARNING,
        !           340:                                    "hd%d%c: overlaps open partition (%c)\n",
        !           341:                                    unit, part + 'a',
        !           342:                                    pp - lp->d_partitions + 'a');
        !           343:                }
        !           344:        }
        !           345:        if (part >= lp->d_npartitions)
        !           346:                return(ENXIO);
        !           347:        dk->dk_openpart |= mask;
        !           348:        switch (fmt) {
        !           349:        case S_IFCHR:
        !           350:                dk->dk_copenpart |= mask;
        !           351:                break;
        !           352:        case S_IFBLK:
        !           353:                dk->dk_bopenpart |= mask;
        !           354:                break;
        !           355:        }
        !           356:        return(0);
        !           357: }
        !           358: 
        !           359: /* ARGSUSED */
        !           360: hdclose(dev, flags, fmt)
        !           361:        dev_t dev;
        !           362:        int flags, fmt;
        !           363: {
        !           364:        register struct dksoftc *dk;
        !           365:        int mask;
        !           366: 
        !           367:        dk = &dksoftc[hdunit(dev)];
        !           368:        mask = 1 << hdpart(dev);
        !           369:        switch (fmt) {
        !           370:        case S_IFCHR:
        !           371:                dk->dk_copenpart &= ~mask;
        !           372:                break;
        !           373:        case S_IFBLK:
        !           374:                dk->dk_bopenpart &= ~mask;
        !           375:                break;
        !           376:        }
        !           377:        if (((dk->dk_copenpart | dk->dk_bopenpart) & mask) == 0)
        !           378:                dk->dk_openpart &= ~mask;
        !           379:        /*
        !           380:         * Should wait for i/o to complete on this partition
        !           381:         * even if others are open, but wait for work on blkflush().
        !           382:         */
        !           383:        if (dk->dk_openpart == 0) {
        !           384:                int s = spl7();
        !           385:                while (dk->dk_utab.b_actf)
        !           386:                        sleep((caddr_t)dk, PZERO-1);
        !           387:                splx(s);
        !           388:                dk->dk_state = CLOSED;
        !           389:                dk->dk_wlabel = 0;
        !           390:        }
        !           391:        return(0);
        !           392: }
        !           393: 
        !           394: hdinit(dev, flags)
        !           395:        dev_t dev;
        !           396:        int flags;
        !           397: {
        !           398:        register struct dksoftc *dk;
        !           399:        register struct disklabel *lp;
        !           400:        struct vba_device *vi;
        !           401:        int error, unit;
        !           402:        char *msg, *readdisklabel();
        !           403:        extern int cold;
        !           404: 
        !           405:        vi = hddinfo[unit = hdunit(dev)];
        !           406:        dk = &dksoftc[unit];
        !           407:        dk->dk_unit = vi->ui_slave;
        !           408:        dk->dk_ctlr = vi->ui_ctlr;
        !           409: 
        !           410:        if (flags & O_NDELAY) {
        !           411:                dk->dk_state = OPENRAW;
        !           412:                return(0);
        !           413:        }
        !           414: 
        !           415:        error = 0;
        !           416:        lp = &dk->dk_label;
        !           417:        dk->dk_state = RDLABEL;
        !           418:        if (msg = readdisklabel(dev, hdstrategy, lp)) {
        !           419:                if (cold) {
        !           420:                        printf(": %s\n", msg);
        !           421:                        dk->dk_state = CLOSED;
        !           422:                } else {
        !           423:                        log(LOG_ERR, "hd%d: %s\n", unit, msg);
        !           424:                        dk->dk_state = OPENRAW;
        !           425:                }
        !           426: #ifdef COMPAT_42
        !           427:                hdclock(vi->ui_ctlr);
        !           428:                if (!(error = hdreadgeometry(dk)))
        !           429:                        dk->dk_state = OPEN;
        !           430:                hdcunlock(vi->ui_ctlr);
        !           431: #endif
        !           432:        } else
        !           433:                dk->dk_state = OPEN;
        !           434:        wakeup((caddr_t)dk);
        !           435:        return(error);
        !           436: }
        !           437: 
        !           438: hd_setsecsize(dk, lp)
        !           439:        register struct dksoftc *dk;
        !           440:        struct disklabel *lp;
        !           441: {
        !           442:        register int mul;
        !           443: 
        !           444:        /*
        !           445:         * Calculate scaling shift for mapping
        !           446:         * DEV_BSIZE blocks to drive sectors.
        !           447:         */
        !           448:        mul = DEV_BSIZE / lp->d_secsize;
        !           449:        dk->dk_bshift = 0;
        !           450:        while ((mul >>= 1) > 0)
        !           451:                dk->dk_bshift++;
        !           452: }
        !           453: 
        !           454: /* ARGSUSED */
        !           455: hddgo(vm)
        !           456:        struct vba_device *vm;
        !           457: {}
        !           458: 
        !           459: extern int name_ext;
        !           460: hdstrategy(bp)
        !           461:        register struct buf *bp;
        !           462: {
        !           463:        register struct vba_device *vi;
        !           464:        register struct disklabel *lp;
        !           465:        register struct dksoftc *dk;
        !           466:        struct buf *dp;
        !           467:        register int unit;
        !           468:        daddr_t sn, sz, maxsz;
        !           469:        int part, s;
        !           470: 
        !           471:        vi = hddinfo[unit = hdunit(bp->b_dev)];
        !           472:        if (unit >= NHD || vi == 0 || vi->ui_alive == 0) {
        !           473:                bp->b_error = ENXIO;
        !           474:                goto bad;
        !           475:        }
        !           476:        dk = &dksoftc[unit];
        !           477:        if (dk->dk_state < OPEN)
        !           478:                goto q;
        !           479:        if (dk->dk_state != OPEN && (bp->b_flags & B_READ) == 0) {
        !           480:                bp->b_error = EROFS;
        !           481:                goto bad;
        !           482:        }
        !           483:        part = hdpart(bp->b_dev);
        !           484:        if ((dk->dk_openpart & (1 << part)) == 0) {
        !           485:                bp->b_error = ENODEV;
        !           486:                goto bad;
        !           487:        }
        !           488:        lp = &dk->dk_label;
        !           489:        sz = (bp->b_bcount + lp->d_secsize - 1) / lp->d_secsize;
        !           490:        maxsz = lp->d_partitions[part].p_size;
        !           491:        sn = bp->b_blkno << dk->dk_bshift;
        !           492:        if (sn + lp->d_partitions[part].p_offset <= LABELSECTOR &&
        !           493: #if LABELSECTOR != 0
        !           494:            sn + lp->d_partitions[part].p_offset + sz > LABELSECTOR &&
        !           495: #endif
        !           496:            (bp->b_flags & B_READ) == 0 && dk->dk_wlabel == 0) {
        !           497:                bp->b_error = EROFS;
        !           498:                goto bad;
        !           499:        }
        !           500:        if (sn < 0 || sn + sz > maxsz) {
        !           501:                if (sn == maxsz) {
        !           502:                        bp->b_resid = bp->b_bcount;
        !           503:                        goto done;
        !           504:                }
        !           505:                sz = maxsz - sn;
        !           506:                if (sz <= 0) {
        !           507:                        bp->b_error = EINVAL;
        !           508:                        goto bad;
        !           509:                }
        !           510:                bp->b_bcount = sz * lp->d_secsize;
        !           511:        }
        !           512:        bp->b_cylin = (sn + lp->d_partitions[part].p_offset) / lp->d_secpercyl;
        !           513: 
        !           514: q:     s = spl7();
        !           515:        dp = &dk->dk_utab;
        !           516:        disksort(dp, bp);
        !           517:        if (!dp->b_active) {
        !           518:                (void)hdustart(vi);
        !           519:                if (!vi->ui_mi->um_tab.b_active)
        !           520:                        hdcstart(vi->ui_mi);
        !           521:        }
        !           522:        splx(s);
        !           523:        return;
        !           524: bad:
        !           525:        bp->b_flags |= B_ERROR;
        !           526: done:
        !           527:        biodone(bp);
        !           528: }
        !           529: 
        !           530: hdustart(vi)
        !           531:        register struct vba_device *vi;
        !           532: {
        !           533:        register struct buf *bp, *dp;
        !           534:        register struct vba_ctlr *vm;
        !           535:        register struct dksoftc *dk;
        !           536: 
        !           537:        dk = &dksoftc[vi->ui_unit];
        !           538:        dp = &dk->dk_utab;
        !           539: 
        !           540:        /* if queue empty, nothing to do.  impossible? */
        !           541:        if (dp->b_actf == NULL)
        !           542:                return;
        !           543: 
        !           544:        /* place on controller transfer queue */
        !           545:        vm = vi->ui_mi;
        !           546:        if (vm->um_tab.b_actf == NULL)
        !           547:                vm->um_tab.b_actf = dp;
        !           548:        else
        !           549:                vm->um_tab.b_actl->b_forw = dp;
        !           550:        vm->um_tab.b_actl = dp;
        !           551:        dp->b_forw = NULL;
        !           552:        dp->b_active++;
        !           553: }
        !           554: 
        !           555: hdcstart(vm)
        !           556:        register struct vba_ctlr *vm;
        !           557: {
        !           558:        register struct buf *bp;
        !           559:        register struct dksoftc *dk;
        !           560:        register struct disklabel *lp;
        !           561:        register struct master_mcb *master;
        !           562:        register struct mcb *mcb;
        !           563:        struct vba_device *vi;
        !           564:        struct hdcsoftc *hdc;
        !           565:        struct buf *dp;
        !           566:        int sn;
        !           567: 
        !           568:        /* pull a request off the controller queue */
        !           569:        for (;;) {
        !           570:                if ((dp = vm->um_tab.b_actf) == NULL)
        !           571:                        return;
        !           572:                if (bp = dp->b_actf)
        !           573:                        break;
        !           574:                vm->um_tab.b_actf = dp->b_forw;
        !           575:        }
        !           576: 
        !           577:        /* mark controller active */
        !           578:        vm->um_tab.b_active++;
        !           579: 
        !           580:        vi = hddinfo[hdunit(bp->b_dev)];
        !           581:        dk = &dksoftc[vi->ui_unit];
        !           582:        lp = &dk->dk_label;
        !           583:        sn = bp->b_blkno << dk->dk_bshift;
        !           584: 
        !           585:        /* fill in mcb */
        !           586:        mcb = &dk->dk_mcb;
        !           587:        mcb->forw_phaddr = 0;
        !           588:        /* mcb->priority = 0; */
        !           589:        mcb->interrupt = 1;
        !           590:        mcb->command = (bp->b_flags & B_READ) ? HCMD_READ:HCMD_WRITE;
        !           591:        mcb->cyl = bp->b_cylin;
        !           592: /* assumes partition starts on cylinder boundary */
        !           593:        mcb->head = (sn / lp->d_nsectors) % lp->d_ntracks;
        !           594:        mcb->sector = sn % lp->d_nsectors;
        !           595:        mcb->drive = vi->ui_slave;
        !           596:        /* mcb->context = 0;            /* what do we want on interrupt? */
        !           597: 
        !           598:        hdc = &hdcsoftc[vm->um_ctlr];
        !           599:        if (!hd_sgsetup(bp, &hdc->hdc_rbuf, mcb->chain)) {
        !           600:                mcb->chain[0].wcount = (bp->b_bcount+3) >> 2;
        !           601:                mcb->chain[0].memadr =
        !           602:                    vbasetup(bp, &hdc->hdc_rbuf, (int)lp->d_secsize);
        !           603:        }
        !           604: 
        !           605:        if (vi->ui_dk >= 0) {
        !           606:                dk_busy |= 1<<vi->ui_dk;
        !           607:                dk_xfer[vi->ui_dk]++;
        !           608:                dk_wds[vi->ui_dk] += bp->b_bcount>>6;
        !           609:        }
        !           610: 
        !           611:        master = &hdc->hdc_mcb;
        !           612:        master->mcw = MCL_QUEUED;
        !           613:        master->interrupt = HDCINTERRUPT + vm->um_ctlr;
        !           614:        master->forw_phaddr = (u_long)vtoph((struct proc *)NULL, mcb);
        !           615:        hdc->hdc_reg->master_mcb = (u_long)hdc->hdc_mcbp;
        !           616: }
        !           617: 
        !           618: /*
        !           619:  * Wait for controller to finish current operation
        !           620:  * so that direct controller accesses can be done.
        !           621:  */
        !           622: hdclock(ctlr)
        !           623:        int ctlr;
        !           624: {
        !           625:        register struct vba_ctlr *vm = hdcminfo[ctlr];
        !           626:        register struct hdcsoftc *hdc;
        !           627:        int s;
        !           628: 
        !           629:        hdc = &hdcsoftc[ctlr];
        !           630:        s = spl7();
        !           631:        while (vm->um_tab.b_active || hdc->hdc_flags & HDC_LOCKED) {
        !           632:                hdc->hdc_flags |= HDC_WAIT;
        !           633:                sleep((caddr_t)hdc, PRIBIO);
        !           634:        }
        !           635:        hdc->hdc_flags |= HDC_LOCKED;
        !           636:        splx(s);
        !           637: }
        !           638: 
        !           639: /*
        !           640:  * Continue normal operations after pausing for 
        !           641:  * munging the controller directly.
        !           642:  */
        !           643: hdcunlock(ctlr)
        !           644:        int ctlr;
        !           645: {
        !           646:        register struct vba_ctlr *vm;
        !           647:        register struct hdcsoftc *hdc = &hdcsoftc[ctlr];
        !           648: 
        !           649:        hdc->hdc_flags &= ~HDC_LOCKED;
        !           650:        if (hdc->hdc_flags & HDC_WAIT) {
        !           651:                hdc->hdc_flags &= ~HDC_WAIT;
        !           652:                wakeup((caddr_t)hdc);
        !           653:        } else {
        !           654:                vm = hdcminfo[ctlr];
        !           655:                if (vm->um_tab.b_actf)
        !           656:                        hdcstart(vm);
        !           657:        }
        !           658: }
        !           659: 
        !           660: hdintr(ctlr)
        !           661:        int ctlr;
        !           662: {
        !           663:        register struct buf *bp, *dp;
        !           664:        register struct vba_ctlr *vm;
        !           665:        register struct vba_device *vi;
        !           666:        register struct hdcsoftc *hdc;
        !           667:        register struct mcb *mcb;
        !           668:        struct master_mcb *master;
        !           669:        register int status;
        !           670:        int timedout;
        !           671:        struct dksoftc *dk;
        !           672: 
        !           673:        hdc = &hdcsoftc[ctlr];
        !           674:        master = &hdc->hdc_mcb;
        !           675:        uncache(&master->mcs);
        !           676:        uncache(&master->context);
        !           677: 
        !           678:        vm = hdcminfo[ctlr];
        !           679:        if (!vm->um_tab.b_active || !(master->mcs&MCS_DONE)) {
        !           680:                printf("hd%d: stray interrupt\n", ctlr);
        !           681:                return;
        !           682:        }
        !           683: 
        !           684:        dp = vm->um_tab.b_actf;
        !           685:        bp = dp->b_actf;
        !           686:        vi = hddinfo[hdunit(bp->b_dev)];
        !           687:        dk = &dksoftc[vi->ui_unit];
        !           688:        if (vi->ui_dk >= 0)
        !           689:                dk_busy &= ~(1<<vi->ui_dk);
        !           690:        timedout = (hdc->hdc_wticks >= HDCMAXTIME);
        !           691: 
        !           692:        mcb = &dk->dk_mcb;
        !           693: 
        !           694:        if (master->mcs & (MCS_SOFTERROR | MCS_FATALERROR) || timedout)
        !           695:                hdcerror(ctlr, *(u_long *)master->xstatus);
        !           696:        else 
        !           697:                hdc->hdc_wticks = 0;
        !           698:        if (vm->um_tab.b_active) {
        !           699:                vm->um_tab.b_active = 0;
        !           700:                vm->um_tab.b_actf = dp->b_forw;
        !           701:                dp->b_active = 0;
        !           702:                dp->b_errcnt = 0;
        !           703:                dp->b_actf = bp->av_forw;
        !           704:                bp->b_resid = 0;
        !           705:                vbadone(bp, &hdc->hdc_rbuf);
        !           706:                biodone(bp);
        !           707:                /* start up now, if more work to do */
        !           708:                if (dp->b_actf)
        !           709:                        hdustart(vi);
        !           710:                else if (dk->dk_openpart == 0)
        !           711:                        wakeup((caddr_t)dk);
        !           712:        }
        !           713:        /* if there are devices ready to transfer, start the controller. */
        !           714:        if (hdc->hdc_flags & HDC_WAIT) {
        !           715:                hdc->hdc_flags &= ~HDC_WAIT;
        !           716:                wakeup((caddr_t)hdc);
        !           717:        } else if (vm->um_tab.b_actf)
        !           718:                hdcstart(vm);
        !           719: }
        !           720: 
        !           721: hdioctl(dev, cmd, data, flag)
        !           722:        dev_t dev;
        !           723:        int cmd, flag;
        !           724:        caddr_t data;
        !           725: {
        !           726:        register int unit;
        !           727:        register struct dksoftc *dk;
        !           728:        register struct disklabel *lp;
        !           729:        int error;
        !           730: 
        !           731:        unit = hdunit(dev);
        !           732:        dk = &dksoftc[unit];
        !           733:        lp = &dk->dk_label;
        !           734:        error = 0;
        !           735:        switch (cmd) {
        !           736:        case DIOCGDINFO:
        !           737:                *(struct disklabel *)data = *lp;
        !           738:                break;
        !           739:        case DIOCGPART:
        !           740:                ((struct partinfo *)data)->disklab = lp;
        !           741:                ((struct partinfo *)data)->part =
        !           742:                    &lp->d_partitions[hdpart(dev)];
        !           743:                break;
        !           744:        case DIOCSDINFO:
        !           745:                if ((flag & FWRITE) == 0)
        !           746:                        error = EBADF;
        !           747:                else
        !           748:                        error = setdisklabel(lp, (struct disklabel *)data,
        !           749:                            (dk->dk_state == OPENRAW) ? 0 : dk->dk_openpart);
        !           750:                if (error == 0 && dk->dk_state == OPENRAW)
        !           751:                        dk->dk_state = OPEN;
        !           752:                break;
        !           753:        case DIOCWLABEL:
        !           754:                if ((flag & FWRITE) == 0)
        !           755:                        error = EBADF;
        !           756:                else
        !           757:                        dk->dk_wlabel = *(int *)data;
        !           758:                break;
        !           759:        case DIOCWDINFO:
        !           760:                if ((flag & FWRITE) == 0)
        !           761:                        error = EBADF;
        !           762:                else if ((error = setdisklabel(lp, (struct disklabel *)data,
        !           763:                    (dk->dk_state == OPENRAW) ? 0 : dk->dk_openpart)) == 0) {
        !           764:                        int wlab;
        !           765: 
        !           766:                        if (error == 0 && dk->dk_state == OPENRAW)
        !           767:                                dk->dk_state = OPEN;
        !           768:                        /* simulate opening partition 0 so write succeeds */
        !           769:                        dk->dk_openpart |= (1 << 0);            /* XXX */
        !           770:                        wlab = dk->dk_wlabel;
        !           771:                        dk->dk_wlabel = 1;
        !           772:                        error = writedisklabel(dev, hdstrategy, lp);
        !           773:                        dk->dk_openpart = dk->dk_copenpart | dk->dk_bopenpart;
        !           774:                        dk->dk_wlabel = wlab;
        !           775:                }
        !           776:                break;
        !           777:        default:
        !           778:                error = ENOTTY;
        !           779:                break;
        !           780:        }
        !           781:        return (error);
        !           782: }
        !           783: 
        !           784: /*
        !           785:  * Watch for lost interrupts.
        !           786:  */
        !           787: hdcwatch()
        !           788: {
        !           789:        register struct hdcsoftc *hdc;
        !           790:        register struct vba_ctlr **vmp;
        !           791:        register int ctlr;
        !           792:        int s;
        !           793: 
        !           794:        timeout(hdcwatch, (caddr_t)0, hz);
        !           795:        for (vmp = hdcminfo, hdc = hdcsoftc, ctlr = 0; ctlr < NHDC;
        !           796:            ++ctlr, ++vmp, ++hdc) {
        !           797:                if (*vmp == 0 || (*vmp)->um_alive == 0)
        !           798:                        continue;
        !           799:                s = spl7();
        !           800:                if ((*vmp)->um_tab.b_active &&
        !           801:                    hdc->hdc_wticks++ >= HDCMAXTIME) {
        !           802:                        printf("hd%d: lost interrupt\n", ctlr);
        !           803:                        hdintr(ctlr);
        !           804:                }
        !           805:                splx(s);
        !           806:        }
        !           807: }
        !           808: 
        !           809: hddump(dev)
        !           810:        dev_t dev;
        !           811: {
        !           812:        return(ENXIO);
        !           813: }
        !           814: 
        !           815: hdsize(dev)
        !           816:        dev_t dev;
        !           817: {
        !           818:        register int unit = hdunit(dev);
        !           819:        register struct dksoftc *dk;
        !           820:        struct vba_device *vi;
        !           821:        struct disklabel *lp;
        !           822: 
        !           823:        if (unit >= NHD || (vi = hddinfo[unit]) == 0 || vi->ui_alive == 0 ||
        !           824:            (dk = &dksoftc[unit])->dk_state != OPEN)
        !           825:                return (-1);
        !           826:        lp = &dk->dk_label;
        !           827:        return ((int)lp->d_partitions[hdpart(dev)].p_size >> dk->dk_bshift);
        !           828: }
        !           829: 
        !           830: hdimcb(dk)
        !           831:        register struct dksoftc *dk;
        !           832: {
        !           833:        register struct master_mcb *master;
        !           834:        register struct mcb *mcb;
        !           835:        register struct hdcsoftc *hdc;
        !           836:        int timeout;
        !           837: 
        !           838:        /* fill in mcb */
        !           839:        mcb = &dk->dk_mcb;
        !           840:        mcb->interrupt = 0;
        !           841:        mcb->forw_phaddr = 0;
        !           842:        mcb->drive = dk->dk_unit;
        !           843: 
        !           844:        hdc = &hdcsoftc[dk->dk_ctlr];
        !           845:        master = &hdc->hdc_mcb;
        !           846: 
        !           847:        /* fill in master mcb */
        !           848:        master->mcw = MCL_IMMEDIATE;
        !           849:        master->forw_phaddr = (u_long)vtoph((struct proc *)NULL, mcb);
        !           850:        master->mcs = 0;
        !           851: 
        !           852:        /* kick controller and wait */
        !           853:        hdc->hdc_reg->master_mcb = (u_long)hdc->hdc_mcbp;
        !           854:        for (timeout = 15000; timeout; --timeout) {
        !           855:                DELAY(1000);
        !           856:                mtpr(PADC, 0);
        !           857:                if (master->mcs&MCS_FATALERROR) {
        !           858:                        printf("hdc%d: fatal error\n", dk->dk_ctlr);
        !           859:                        hdcerror(dk->dk_ctlr, *(u_long *)master->xstatus);
        !           860:                        return(1);
        !           861:                }
        !           862:                if (master->mcs&MCS_DONE)
        !           863:                        return(0);
        !           864:        }
        !           865:        printf("hdc%d: timed out\n", dk->dk_ctlr);
        !           866:        return(1);
        !           867: }
        !           868: 
        !           869: hdcerror(ctlr, code)
        !           870:        int ctlr;
        !           871:        u_long code;
        !           872: {
        !           873:        printf("hd%d: error %lx\n", ctlr, code);
        !           874: }
        !           875: 
        !           876: #ifdef COMPAT_42
        !           877: hdreadgeometry(dk)
        !           878:        struct dksoftc *dk;
        !           879: {
        !           880:        static geometry_sector geometry;
        !           881:        register struct mcb *mcb;
        !           882:        register struct disklabel *lp;
        !           883:        geometry_block *geo;
        !           884:        int cnt;
        !           885: 
        !           886:        /*
        !           887:         * Read the geometry block (at head = 0 sector = 0 of the drive
        !           888:         * definition cylinder), validate it (must have the correct version
        !           889:         * number, header, and checksum).
        !           890:         */
        !           891:        mcb = &dk->dk_mcb;
        !           892:        mcb->command = HCMD_READ;
        !           893:        mcb->cyl = dk->dk_def_cyl;
        !           894:        mcb->head = 0;
        !           895:        mcb->sector = 0;
        !           896:        mcb->chain[0].wcount = sizeof(geometry_sector) / sizeof(long);
        !           897:        mcb->chain[0].memadr  = (u_long)vtoph((struct process *)0, &geometry);
        !           898:        /* mcb->chain[0].memadr = (long)&geometry; */
        !           899:        if (hdimcb(dk)) {
        !           900:                printf("hd%d: can't read default geometry.\n", dk->dk_unit);
        !           901:                return(1);
        !           902:        }
        !           903:        geo = &geometry.geometry_block;
        !           904:        if (geo->version > 64000  ||  geo->version < 0) {
        !           905:                printf("hd%d: bad default geometry version#.\n", dk->dk_unit);
        !           906:                return(1);
        !           907:        }
        !           908:        if (bcmp(&geo->id[0], GB_ID, GB_ID_LEN)) {
        !           909:                printf("hd%d: bad default geometry header.\n", dk->dk_unit);
        !           910:                return(1);
        !           911:        }
        !           912:        GB_CHECKSUM(geo, cnt);
        !           913:        if (geometry.checksum != cnt) {
        !           914:                printf("hd%d: bad default geometry checksum.\n", dk->dk_unit);
        !           915:                return(1);
        !           916:        }
        !           917:        lp = &dk->dk_label;
        !           918: 
        !           919:        /* 1K block in Harris geometry; convert to sectors for disklabels */
        !           920:        for (cnt = 0; cnt < GB_MAXPART; cnt++) {
        !           921:                lp->d_partitions[cnt].p_offset =
        !           922:                    geo->partition[cnt].start * (1024 / lp->d_secsize);
        !           923:                lp->d_partitions[cnt].p_size =
        !           924:                    geo->partition[cnt].length * (1024 / lp->d_secsize);
        !           925:        }
        !           926:        lp->d_npartitions = GB_MAXPART;
        !           927:        return(0);
        !           928: }
        !           929: #endif /* COMPAT_42 */
        !           930: #endif /* NHD */

unix.superglobalmegacorp.com

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