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

unix.superglobalmegacorp.com

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