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

unix.superglobalmegacorp.com

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