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

unix.superglobalmegacorp.com

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