Annotation of 43BSDTahoe/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 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.