Annotation of researchv10no/sys/io/hp.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * MASSBUS SMD disk driver
        !             3:  */
        !             4: 
        !             5: #include "sys/param.h"
        !             6: #include "sys/buf.h"
        !             7: #include "sys/conf.h"
        !             8: #include "sys/dir.h"
        !             9: #include "sys/user.h"
        !            10: #include "sys/hp.h"
        !            11: #include "sys/mbaddr.h"
        !            12: #include "sys/mbsts.h"
        !            13: #include "sys/bad144.h"
        !            14: #include "sys/diskio.h"
        !            15: #include "sys/file.h"
        !            16: 
        !            17: /*
        !            18:  * hardware registers
        !            19:  */
        !            20: 
        !            21: struct hpdevice {
        !            22:        int     hpcs1;          /* control and status register 1 */
        !            23:        int     hpds;           /* drive status */
        !            24:        int     hper1;          /* error register 1 */
        !            25:        int     hpmr;           /* maintenance */ 
        !            26:        int     hpas;           /* attention summary */
        !            27:        int     hpda;           /* desired address register */
        !            28:        int     hpdt;           /* drive type */
        !            29:        int     hpla;           /* look ahead */
        !            30:        int     hpsn;           /* serial number */
        !            31:        int     hpof;           /* offset register */
        !            32:        int     hpdc;           /* desired cylinder address register */
        !            33:        int     hpcc;           /* current cylinder */
        !            34: /* on an rp drive, mr2 is called er2 and er2 is called er3 */
        !            35: /* we use rm terminology here */
        !            36:        int     hpmr2;          /* maintenance register 2 */
        !            37:        int     hper2;          /* error register 2 */
        !            38:        int     hpec1;          /* burst error bit position */
        !            39:        int     hpec2;          /* burst error bit pattern */
        !            40: };
        !            41: 
        !            42: /*
        !            43:  * hpcs1
        !            44:  */
        !            45: 
        !            46: #define        HP_GO   0000001
        !            47: 
        !            48: #define        HP_SEEK         004             /* seek */
        !            49: #define        HP_RECAL        006             /* recalibrate */
        !            50: #define        HP_DCLR         010             /* drive clear */
        !            51: #define        HP_OFFSET       014             /* offset */
        !            52: #define        HP_RTC          016             /* return to center-line */
        !            53: #define        HP_PRESET       020             /* read-in preset */
        !            54: #define        HP_SEARCH       030             /* search */
        !            55: #define        HP_WCOM         060             /* write */
        !            56: #define        HP_RCOM         070             /* read data */
        !            57: 
        !            58: /*
        !            59:  * hpds
        !            60:  */
        !            61: #define        HPDS_ERR        0040000         /* composite drive error */
        !            62: #define        HPDS_PIP        0020000         /* positioning in progress */
        !            63: #define        HPDS_MOL        0010000         /* medium on line */
        !            64: #define        HPDS_DPR        0000400         /* drive present */
        !            65: #define        HPDS_DRY        0000200         /* drive ready */
        !            66: #define        HPDS_VV         0000100         /* volume valid */
        !            67: #define        HPDS_DREADY     (HPDS_DPR|HPDS_DRY|HPDS_MOL|HPDS_VV)
        !            68: 
        !            69: /*
        !            70:  * hper1
        !            71:  */
        !            72: #define        HPER1_DCK       0100000         /* data check */
        !            73: #define        HPER1_WLE       0004000         /* write lock error */
        !            74: #define        HPER1_ECH       0000100         /* ecc hard error */
        !            75: #define        HPER1_FER       0000020         /* format error */
        !            76: 
        !            77: /*
        !            78:  * hpdt
        !            79:  */
        !            80: #define        HPDT_TYPE       0x1ff
        !            81: #define        HPDT_RP05       021
        !            82: #define        HPDT_RP06       022
        !            83: #define        HPDT_RP07       042
        !            84: #define        HPDT_RM03       024
        !            85: #define        HPDT_RM05       027
        !            86: #define        HPDT_FUJI       025
        !            87: 
        !            88: /*
        !            89:  * hpcc: emulex hack
        !            90:  */
        !            91: #define        HPHR_MAXCYL     0100027         /* max cyl address */
        !            92: #define        HPHR_MAXTRAK    0100030         /* max track address */
        !            93: #define        HPHR_MAXSECT    0100031         /* max sector address */
        !            94: 
        !            95: /*
        !            96:  * hpof
        !            97:  */
        !            98: #define        HPOF_FMT22      0010000         /* 16 bit format */
        !            99: #define        HPOF_P400       0020            /*  +400 uinches */
        !           100: #define        HPOF_M400       0220            /*  -400 uinches */
        !           101: #define        HPOF_P800       0040            /*  +800 uinches */
        !           102: #define        HPOF_M800       0240            /*  -800 uinches */
        !           103: #define        HPOF_P1200      0060            /* +1200 uinches */
        !           104: #define        HPOF_M1200      0260            /* -1200 uinches */
        !           105: 
        !           106: /*
        !           107:  * hper2
        !           108:  */
        !           109: #define        HPER2_BSE       0100000         /* bad sector */
        !           110: 
        !           111: #define        SECTOR  512     /* size of a hardware sector */
        !           112: 
        !           113: /*
        !           114:  * monstrous size tables
        !           115:  * one per type of drive
        !           116:  */
        !           117: struct size
        !           118: {
        !           119:        daddr_t nblocks;
        !           120:        daddr_t blkoff;
        !           121: };
        !           122: struct size hp6_sizes[8] = {
        !           123:        15884,  0,              /* A=cyl 0 thru 37 */
        !           124:        33440,  15884,          /* B=cyl 38 thru 117 */
        !           125:        340670, 0,              /* C=cyl 0 thru 814 */
        !           126:        0,      0,
        !           127:        0,      0,
        !           128:        0,      0,
        !           129: #ifndef NOBADSECT
        !           130:        291280, 49324,          /* G=cyl 118 thru 814 */
        !           131: #else
        !           132:        291346, 49324,
        !           133: #endif
        !           134:        0,      0,
        !           135: };
        !           136: struct size rm3_sizes[8] = {
        !           137:        15884,  0,              /* A=cyl 0 thru 99 */
        !           138:        33440,  16000,          /* B=cyl 100 thru 309 */
        !           139:        131680, 0,              /* C=cyl 0 thru 822 */
        !           140:        0,      0,
        !           141:        0,      0,
        !           142:        0,      0,
        !           143: #ifndef NOBADSECT
        !           144:        81984,  49600,          /* G=cyl 310 thru 822 */
        !           145: #else
        !           146:        82080,  49600,
        !           147: #endif
        !           148:        113280, 18400,          /* H=cyl 115 thru 708 -- ex 32v */
        !           149: };
        !           150: struct size rm5_sizes[8] = {
        !           151:        15884,  0,              /* A=cyl 0 thru 26 */
        !           152:        33440,  16416,          /* B=cyl 27 thru 81 */
        !           153:        500384, 0,              /* C=cyl 0 thru 822 */
        !           154:        15884,  341696,         /* D=cyl 562 thru 588 */
        !           155:        55936,  358112,         /* E=cyl 589 thru 680 */
        !           156: #ifndef NOBADSECT
        !           157:        86240,  414048,         /* F=cyl 681 thru 822 */
        !           158:        158592, 341696,         /* G=cyl 562 thru 822 */
        !           159: #else
        !           160:        86636,  414048,
        !           161:        158688, 341696,
        !           162: #endif
        !           163:        291346, 49856,          /* H=cyl 82 thru 561 */
        !           164: };
        !           165: struct size mfj_sizes[8] = {
        !           166:        10240,  0,              /* A=cyl 0 thru 31 */
        !           167:        20480,  10240,          /* B=cyl 32 thru 95 */
        !           168:        232640, 30720,          /* C=cyl 96 thru 822 */
        !           169:        0,      0,
        !           170:        0,      0,
        !           171:        0,      0,
        !           172:        0,      0,
        !           173:        0,      0,
        !           174: };
        !           175: struct size eagle_sizes[8] ={
        !           176:        27520,  0,              /* A=cyl 0 thru 31 */
        !           177:        27520,  27520,          /* B=cyl 32 thru 63 */
        !           178:        667360, 55040,          /* C=cyl 64 thru 839 */
        !           179:        232640, 55040,          /* D=cyl 64 thru 340 (partial) */
        !           180:        232640, 293260,         /* E=cyl 341 thru 617 (partial) */
        !           181:        0,      0,
        !           182:        0,      0,
        !           183:        0,      0,
        !           184: };
        !           185: /* 48 sector Emulex Eagle */
        !           186: struct size eag48_sizes[8] = { /* cyl 841 used for bad sectors + info */
        !           187: #ifndef OLDPART
        !           188:        11*960,   0*960,        /* A = cyl 0 thru 10            for / */
        !           189:        22*960,  11*960,        /* B = cyl 11 thru 32           for swap */
        !           190:        842*960,  0*960,        /* C = all cyl 0 thru 841       for testing */
        !           191:        16*960,  33*960,        /* D = cyl 33 thru 48           for /usr/guest */
        !           192:        66*960,  49*960,        /* E = cyl 49 thru 114          for /usr/src */
        !           193:        242*960,115*960,        /* F = cyl 115 thru 356         nearly 1/3 */
        !           194:        242*960,357*960,        /* G = cyl 357 thru 598         nearly 1/3 */
        !           195:        242*960,599*960,        /* H = cyl 599 thru 840         nearly 1/3 */
        !           196: #else  /* old jones partitions */
        !           197:        45*960,   0*960,        /* A = cyl 0 thru 44            for /tmp */
        !           198:        64*960,  45*960,        /* B = cyl 45 thru 108          for swap */
        !           199:        842*960,  0*960,        /* C = all cyl 0 thru 841       for testing */
        !           200:        244*960,109*960,        /* D = cyl 109 thru 352         nearly 1/3 */
        !           201:        244*960,353*960,        /* E = cyl 353 thru 596         nearly 1/3 */
        !           202:        244*960,597*960,        /* F = cyl 597 thru 840         nearly 1/3 */
        !           203:        0,      0*960,  /* G = cyl 0 thru 402           nearly 1/2 */
        !           204:        0,      0*960,  /* H = cyl 438 thru 840         nearly 1/2 */
        !           205: #endif
        !           206: };
        !           207: struct size hp7_sizes[8] = {
        !           208:        15884,  0,              /* A=cyl 0 thru 9 */
        !           209:        64000,  16000,          /* B=cyl 10 thru 49 */
        !           210:        1008000,0,              /* C=cyl 0 thru 629 */
        !           211:        504000, 0,              /* D=cyl 0 thru 314 */
        !           212:        504000, 504000,         /* E=cyl 315 thru 629 */
        !           213:        928000, 80000,          /* F=cyl 50 thru 629 */
        !           214:        0,      0,
        !           215:        0,      0,
        !           216: };
        !           217: 
        !           218: /*
        !           219:  * tables of per-drive info, mostly sizes of things
        !           220:  * indexed by numbers in hptypes
        !           221:  */
        !           222: 
        !           223: struct hptype hptype[] = {
        !           224:        HPDT_RM03, 32, 5, 3, 4, 32*5,   823,    rm3_sizes,      /* RM03 */
        !           225:        HPDT_RM05, 32, 19, 2, 3, 32*19, 823,    rm5_sizes,      /* RM05 */
        !           226:        HPDT_RP06, 22, 19, 2, 3, 22*19, 815,    hp6_sizes,      /* RP06 */
        !           227:        HPDT_RP05, 22, 19, 2, 3, 22*19, 411,    hp6_sizes,      /* RP05 */
        !           228:        HPDT_RP07, 50, 32, 2, 3, 50*32, 630,    hp7_sizes,      /* RP07 */
        !           229:        /* HPDT_FUJI (emulex) entries must be contiguous and last */
        !           230:        HPDT_FUJI, 32, 10, 2, 3, 32*10, 823,    mfj_sizes,      /* little fujitsu */
        !           231:        HPDT_FUJI, 43, 20, 8, 9, 43*20, 842,    eagle_sizes,    /* eagle */
        !           232:        HPDT_FUJI, 48, 20, 8, 9, 48*20, 842,    eag48_sizes,    /* eagle 48 sectors */
        !           233:        0
        !           234: };
        !           235: 
        !           236: #define        NOFFS   16
        !           237: unsigned char hp_offset[NOFFS] = {
        !           238:     HPOF_P400, HPOF_M400, HPOF_P400, HPOF_M400,
        !           239:     HPOF_P800, HPOF_M800, HPOF_P800, HPOF_M800, 
        !           240:     HPOF_P1200, HPOF_M1200, HPOF_P1200, HPOF_M1200,
        !           241:     0, 0, 0, 0
        !           242: };
        !           243: 
        !           244: /*
        !           245:  * things from config
        !           246:  */
        !           247: extern int hpcnt;
        !           248: extern struct mbaddr hpaddr[];
        !           249: extern struct hpdisk hpdisk[];
        !           250: extern struct buf hpbuf[];
        !           251: extern struct buf hpbadbuf[];
        !           252: extern struct bad144 hpbad[];
        !           253: 
        !           254: /*
        !           255:  * unit flags, hpdisk.flags
        !           256:  */
        !           257: 
        !           258: #define        UACTIVE 01      /* started seek */
        !           259: #define        UXFER   02      /* done with any seeking; ready to transfer */
        !           260: #define        UWOL    04      /* waiting for offline drive */
        !           261: #define        UWAITOL 010     /* waiting and timer has ticked */
        !           262: #define        UHAVBAD 020     /* have read bad block table */
        !           263: #define        UREVEC  040     /* halfway through reading revectored sector */
        !           264: 
        !           265: /*
        !           266:  * device number
        !           267:  * 0100 in the minor device is (temporarily?)
        !           268:  * usurped to indicate bitmapped file systems
        !           269:  * quietly ignore it for now
        !           270:  * when things improve, change the UNIT mask to 037
        !           271:  */
        !           272: 
        !           273: #define        UNIT(d) ((minor(d)>>3) & 027)
        !           274: #define        PART(d) (minor(d) & 07)
        !           275: 
        !           276: /*
        !           277:  * abuse of spare bits of struct buf
        !           278:  */
        !           279: #define        b_cylin b_resid         /* for disksort */
        !           280: 
        !           281: int    hpwstart;
        !           282: int    hpwatch();
        !           283: int    hpwaitdry;
        !           284: 
        !           285: int hpopen(), hpstrategy(), hpread(), hpwrite(), hpioctl();
        !           286: struct cdevsw hpcdev = cdinit(hpopen, nulldev, hpread, hpwrite, hpioctl);
        !           287: struct bdevsw hpbdev = bdinit(hpopen, nulldev, hpstrategy, 0);
        !           288: 
        !           289: hpopen(dev, flag)
        !           290: int dev, flag;
        !           291: {
        !           292:        register struct hpdisk *hp;
        !           293:        register struct hptype *st;
        !           294:        register int p;
        !           295: 
        !           296:        if (hpuinit(UNIT(dev)) == 0) {
        !           297:                u.u_error = ENXIO;
        !           298:                return;
        !           299:        }
        !           300:        hp = &hpdisk[UNIT(dev)];
        !           301:        st = &hptype[hp->type];
        !           302:        p = PART(dev);
        !           303:        if ((hp->pinit & (1<<p)) == 0) {
        !           304:                hp->nblocks[p] = st->sizes[p].nblocks;
        !           305:                hp->blkoff[p] = st->sizes[p].blkoff;
        !           306:                if ((hp->blkoff[p] % st->nspc) != 0) {
        !           307:                        printf("hp minor %d bad blkoff\n", minor(dev));
        !           308:                        u.u_error = EINVAL;
        !           309:                        return;
        !           310:                }
        !           311:                hp->pinit |= (1<<p);
        !           312:        }
        !           313: }
        !           314: 
        !           315: static char hponce;
        !           316: 
        !           317: hpuinit(unit)
        !           318: register int unit;
        !           319: {
        !           320:        register struct hpdevice *reg;
        !           321:        register struct hpdisk *hp;
        !           322: 
        !           323:        if (unit < 0 || unit > hpcnt)
        !           324:                return (0);
        !           325:        hp = &hpdisk[unit];
        !           326:        if (hp->addr)
        !           327:                return (1);
        !           328:        if ((reg = (struct hpdevice *)mbaddr(&hpaddr[unit])) == NULL
        !           329:        ||  badaddr(&reg->hpcs1, sizeof(long))
        !           330:        ||  (reg->hpds & HPDS_DPR) == 0) {
        !           331:                printf("hp%d absent\n", unit);
        !           332:                return (0);
        !           333:        }
        !           334:        if ((hp->type = hputype(reg)) < 0) {
        !           335:                printf("hp%d absent or bad type\n", unit);
        !           336:                return (0);
        !           337:        }
        !           338:        hp->addr = reg;
        !           339:        if (hponce == 0) {
        !           340:                hponce++;
        !           341:                hpwatch();
        !           342:        }
        !           343:        return (1);
        !           344: }
        !           345: 
        !           346: /*
        !           347:  * determine drive type
        !           348:  * this is called by hpdump too;
        !           349:  * be prepared to run without memory management
        !           350:  * return is an index into hpst
        !           351:  */
        !           352: int
        !           353: hputype(reg)
        !           354: register struct hpdevice *reg;
        !           355: {
        !           356:        register int t, i;
        !           357:        register int nsect, ntrak;
        !           358: 
        !           359:        t = reg->hpdt & HPDT_TYPE;
        !           360:        for (i = 0; hptype[i].type; i++)
        !           361:                if (hptype[i].type == t)
        !           362:                        break;
        !           363:        if (hptype[i].type == 0) {
        !           364:                printf("hp type 0%o unknown\n", t);
        !           365:                return (-1);
        !           366:        }
        !           367:        if (hptype[i].type != HPDT_FUJI)
        !           368:                return (i);
        !           369:        /*
        !           370:         * special hackery for emulex
        !           371:         */
        !           372:        reg->hpcc = HPHR_MAXTRAK;
        !           373:        DELAY(2);       /* hack */
        !           374:        ntrak = reg->hpcc + 1;
        !           375:        ntrak &= 0xffff;
        !           376:        reg->hpcc = HPHR_MAXSECT;
        !           377:        DELAY(2);       /* hack */
        !           378:        nsect = reg->hpcc + 1;
        !           379:        nsect &= 0xffff;
        !           380:        for (; hptype[i].type; i++)
        !           381:                if (ntrak == hptype[i].ntrak && nsect == hptype[i].nsect)
        !           382:                        return (i);
        !           383:        /*
        !           384:         * 48-sector eagle known to be last,
        !           385:         * so the following broken-hardware test might work
        !           386:         */
        !           387:        if (nsect == 46) {
        !           388:                printf("hp said ntrak %d nsect %d, eag48 assumed\n", ntrak, nsect);
        !           389:                return (i - 1);
        !           390:        }
        !           391:        printf("hp fuji ntrak %d nsect %d unknown\n", ntrak, nsect);
        !           392:        return (-1);
        !           393: }
        !           394:  
        !           395: /*
        !           396:  * a subtlety:
        !           397:  * b_cylin = cylinder number;
        !           398:  * later, when computing disk address,
        !           399:  * we use b_cylin, and take b_blkno % cylindersize
        !           400:  * i.e. there's an embedded assumption that every disk partition
        !           401:  * begins on a cylinder boundary
        !           402:  */
        !           403: hpstrategy(bp)
        !           404:        register struct buf *bp;
        !           405: {
        !           406:        register struct hpdisk *hp;
        !           407:        register struct hptype *st;
        !           408:        register int unit;
        !           409:        register int part;
        !           410:        long sz;
        !           411:        int s;
        !           412: 
        !           413:        sz = (bp->b_bcount+SECTOR-1)/SECTOR;
        !           414:        unit = UNIT(bp->b_dev);
        !           415:        hp = &hpdisk[unit];
        !           416:        if (hp->addr == NULL) {         /* safety check */
        !           417:                bp->b_flags |= B_ERROR;
        !           418:                iodone(bp);
        !           419:                return;
        !           420:        }
        !           421:        st = &hptype[hp->type];
        !           422:        part = PART(bp->b_dev);
        !           423:        if (bp->b_blkno < 0 || bp->b_blkno+sz > hp->nblocks[part]) {
        !           424:                if (bp->b_blkno == hp->nblocks[part])
        !           425:                        bp->b_resid = bp->b_bcount;
        !           426:                else {  /* partial read too hard for now */
        !           427:                        bp->b_error = ENXIO;
        !           428:                        bp->b_flags |= B_ERROR;
        !           429:                }
        !           430:                iodone(bp);
        !           431:                return;
        !           432:        }
        !           433:        bp->b_cylin = (bp->b_blkno + hp->blkoff[part])/st->nspc;
        !           434:        s = spl6();
        !           435:        disksort(&hp->actf, &hp->actl, bp);
        !           436:        if ((hp->flags & UACTIVE) == 0)
        !           437:                hpustart(hp);
        !           438:        splx(s);
        !           439: }
        !           440: 
        !           441: /*
        !           442:  * unit start:
        !           443:  * if there's a block for this drive, start seeking there
        !           444:  */
        !           445: int hpxfer();
        !           446: 
        !           447: hpustart(hp)
        !           448: register struct hpdisk *hp;
        !           449: {
        !           450:        register struct buf *bp;
        !           451:        register struct hpdevice *reg;
        !           452:        register struct hptype *st;
        !           453:        int sn, csn;
        !           454: 
        !           455:        if ((bp = hp->actf) == NULL)
        !           456:                return;
        !           457:        reg = hp->addr;
        !           458:        if ((reg->hpds & HPDS_VV) == 0) {
        !           459:                reg->hpcs1 = HP_DCLR|HP_GO;
        !           460:                reg->hpcs1 = HP_PRESET|HP_GO;
        !           461:                reg->hpof = HPOF_FMT22;
        !           462:                hp->flags &=~ UHAVBAD;
        !           463:        }
        !           464:        if ((hp->flags & UHAVBAD) == 0) {
        !           465:                hprbad(hp);
        !           466:                bp = hp->actf;
        !           467:                hp->flags |= UHAVBAD;
        !           468:        }
        !           469:        if ((reg->hpds & (HPDS_DPR|HPDS_MOL)) != (HPDS_DPR|HPDS_MOL)) {
        !           470:                hp->flags |= UWOL;
        !           471:                return;
        !           472:        }
        !           473:        if ((hp->flags & UACTIVE) == 0) {       /* start seek if didn't already */
        !           474:                hp->flags |= UACTIVE;
        !           475:                st = &hptype[hp->type];
        !           476:                sn = bp->b_blkno%st->nsect - st->sdist; /* seek here before io */
        !           477:                if (sn < 0)
        !           478:                        sn += st->nsect;
        !           479:                csn = sn - (reg->hpla>>6);
        !           480:                if (csn < 0)
        !           481:                        csn += st->nsect;
        !           482:                if (bp->b_cylin != reg->hpdc    /* seek if off cylinder */
        !           483:                ||  csn > st->rdist) {          /* or not close enough */
        !           484:                        reg->hpdc = bp->b_cylin;
        !           485:                        reg->hpda = sn;
        !           486:                        reg->hpcs1 = HP_SEARCH|HP_GO;
        !           487:                        return;
        !           488:                }
        !           489:        }
        !           490:        if ((hp->flags & UXFER) == 0) { /* seek done, time for transfer */
        !           491:                hp->flags |= UXFER;
        !           492:                mbstart(&hpaddr[UNIT(bp->b_dev)], bp, hpxfer);
        !           493:        }
        !           494: }
        !           495: 
        !           496: /*
        !           497:  * start transfer
        !           498:  */
        !           499: hpxfer(bp)
        !           500: register struct buf *bp;
        !           501: {
        !           502:        register struct hpdisk *hp;
        !           503:        register struct hpdevice *reg;
        !           504:        register struct hptype *st;
        !           505:        int sn, tn;
        !           506: 
        !           507:        hp = &hpdisk[UNIT(bp->b_dev)];
        !           508:        st = &hptype[hp->type];
        !           509:        sn = bp->b_blkno%st->nspc;
        !           510:        tn = sn/st->nsect;
        !           511:        sn %= st->nsect;
        !           512:        reg = hp->addr;
        !           513:        if ((reg->hpds & HPDS_DREADY) != HPDS_DREADY) {
        !           514:                printf("hp%d: not ready\n", UNIT(bp->b_dev));
        !           515:                hp->errcnt = 0;
        !           516:                hp->actf = bp->av_forw;
        !           517:                hp->flags &=~ (UACTIVE|UXFER);
        !           518:                bp->b_flags |= B_ERROR;
        !           519:                iodone(bp);
        !           520:                return;
        !           521:        }
        !           522:        reg->hpdc = bp->b_cylin;
        !           523:        reg->hpda = (tn << 8) + sn;
        !           524:        if (bp->b_flags & B_READ)
        !           525:                reg->hpcs1 = HP_RCOM|HP_GO;
        !           526:        else
        !           527:                reg->hpcs1 = HP_WCOM|HP_GO;
        !           528: }
        !           529: 
        !           530: /*
        !           531:  * interrupt, passed from MBA code
        !           532:  */
        !           533: hp0int(unit, mbsr, mbbc, attn)
        !           534: int unit, mbsr, mbbc, attn;
        !           535: {
        !           536:        register struct hpdisk *hp;
        !           537: 
        !           538:        hp = &hpdisk[unit];
        !           539:        if (hp->addr == 0) {
        !           540:                if (hpuinit(unit) == 0) {
        !           541:                        printf("hp%d: hopeless interrupt\n", unit);
        !           542:                        return;         /* but ATTN wasn't cleared; will recur */
        !           543:                }
        !           544:                /* init ok, so addr nonzero, so can clear it */
        !           545:        }
        !           546:        hp->addr->hpas = attn;
        !           547:        if (hp->flags & UXFER)
        !           548:                hpxdone(hp, mbsr, mbbc);
        !           549:        if ((hp->flags & UXFER) == 0)
        !           550:                hpustart(hp);
        !           551: }
        !           552: 
        !           553: /*
        !           554:  * transfer stopped:
        !           555:  * because it's done, or because of an error
        !           556:  * common convention in error-sniffing routines:
        !           557:  * return 1 if the error was recovered
        !           558:  * and the device has been restarted
        !           559:  * return 0 if this transfer has been abandoned
        !           560:  * leave flags & UXFER set if we're all done;
        !           561:  * clear UXFER if the transfer should be retried
        !           562:  */
        !           563: 
        !           564: #define        ERRCMIN 16      /* after this many errors, try offsets */
        !           565: #define        ERRCAL(e) (((e)%8)==4)  /* try recal this often */
        !           566: #define        ERRMAX  28      /* after this many errors, give up on transfer */
        !           567: 
        !           568: hpxdone(hp, mbsr, mbbc)
        !           569: register struct hpdisk *hp;
        !           570: int mbsr, mbbc;
        !           571: {
        !           572:        register struct hpdevice *reg;
        !           573:        register struct buf *bp;
        !           574: 
        !           575:        reg = hp->addr;
        !           576:        bp = hp->actf;
        !           577:        if ((reg->hpds&HPDS_ERR) || (mbsr&MBSR_EBITS)) {
        !           578:                if (hpwhaterr(hp, mbsr, mbbc))
        !           579:                        return;
        !           580:                reg->hpcs1 = HP_DCLR|HP_GO;
        !           581:        }
        !           582:        if (hp->recal && hpmorecal(hp))
        !           583:                return;
        !           584:        if (hp->flags & UREVEC && hpbadcont(hp))
        !           585:                return;
        !           586:        if (hp->flags & UXFER) {        /* `active' means we're done */
        !           587:                if (hp->errcnt >= ERRCMIN) {
        !           588:                        reg->hpof = HPOF_FMT22;
        !           589:                        reg->hpcs1 = HP_RTC|HP_GO;
        !           590:                        while (reg->hpds & HPDS_PIP)
        !           591:                                DELAY(25);
        !           592:                }
        !           593:                hp->errcnt = 0;
        !           594:                hp->flags &=~ (UACTIVE|UXFER);
        !           595:                hp->actf = bp->av_forw;
        !           596:                bp->b_resid = mbbc;
        !           597:                iodone(bp);
        !           598:        }
        !           599: }
        !           600: 
        !           601: /*
        !           602:  * sort out errors
        !           603:  */
        !           604: 
        !           605: hpwhaterr(hp, mbsr, mbbc)
        !           606: register struct hpdisk *hp;
        !           607: int mbsr, mbbc;
        !           608: {
        !           609:        register struct hpdevice *reg;
        !           610:        register struct buf *bp;
        !           611:        register int i;
        !           612: 
        !           613:        reg = hp->addr;
        !           614:        bp = hp->actf;
        !           615:        /*
        !           616:         * let registers settle
        !           617:         */
        !           618:        i = 0;
        !           619:        while ((reg->hpds & HPDS_DRY) == 0) {
        !           620:                if (++i > 512)
        !           621:                        break;
        !           622:                hpwaitdry++;
        !           623:        }
        !           624:        if (reg->hper1 & HPER1_WLE) {
        !           625:                printf("hp%d: write locked\n", UNIT(bp->b_dev));
        !           626:                bp->b_flags |= B_ERROR;
        !           627:                return (0);             /* finished */
        !           628:        }
        !           629:        if ((reg->hper2 & HPER2_BSE || reg->hper1 & HPER1_FER)
        !           630:        &&  hpbadrep(hp, mbbc))
        !           631:                return (1);             /* restarted, reading replacement */
        !           632:        if (++hp->errcnt > ERRMAX) {
        !           633:                harderr(bp, "hp");
        !           634:                printf("mbsr %o er1 %o er2 %o\n",
        !           635:                        mbsr, reg->hper1&0177777, reg->hper2&0177777);
        !           636:                bp->b_flags |= B_ERROR;
        !           637:                return (0);             /* finished */
        !           638:        }
        !           639:        if (bp->b_flags & B_READ
        !           640:        &&  (reg->hper1 & (HPER1_DCK|HPER1_ECH)) == HPER1_DCK)
        !           641:                return (hpecc(hp, mbbc));       /* restart or finish */
        !           642:        /*
        !           643:         * hard error: clear and try again,
        !           644:         * perhaps with recal
        !           645:         */
        !           646:        if (ERRCAL(hp->errcnt)) {
        !           647:                hpstrecal(hp);
        !           648:                return (1);     /* restarted */
        !           649:        }
        !           650:        hp->flags &=~ UXFER;
        !           651:        return (0);             /* please restart me */
        !           652: }
        !           653: 
        !           654: /*
        !           655:  * recalibration state machine
        !           656:  * walks through the sequence
        !           657:  *     RECAL
        !           658:  *     SEEK back to the cylinder we wanted
        !           659:  *     perhaps offset the heads slightly
        !           660:  *     and try the operation again
        !           661:  */
        !           662: 
        !           663: hpstrecal(hp)
        !           664: register struct hpdisk *hp;
        !           665: {
        !           666: 
        !           667:        hp->addr->hpcs1 = HP_DCLR|HP_GO;
        !           668:        hp->addr->hpcs1 = HP_RECAL|HP_GO;
        !           669:        hp->recal = 1;
        !           670: }
        !           671: 
        !           672: hpmorecal(hp)
        !           673: register struct hpdisk *hp;
        !           674: {
        !           675:        register struct hpdevice *reg;
        !           676: 
        !           677:        reg = hp->addr;
        !           678:        switch (hp->recal) {
        !           679:        case 1:         /* did RECAL, time to seek */
        !           680:                reg->hpdc = hp->actf->b_cylin;
        !           681:                reg->hpcs1 = HP_SEEK|HP_GO;
        !           682:                hp->recal++;
        !           683:                return (1);
        !           684: 
        !           685:        case 2:         /* did seek, time for offset */
        !           686:                if (hp->errcnt > ERRCMIN && hp->actf->b_flags & B_READ) {
        !           687:                        reg->hpof = hp_offset[hp->errcnt%NOFFS]|HPOF_FMT22;
        !           688:                        reg->hpcs1 = HP_OFFSET|HP_GO;
        !           689:                        hp->recal++;
        !           690:                        return (1);
        !           691:                }
        !           692:                /* too soon or a write, fall through */
        !           693:        default:        /* time to restart the transfer */
        !           694:                hp->recal = 0;
        !           695:                hp->flags &=~ UXFER;
        !           696:                return (0);
        !           697:        }
        !           698: }
        !           699: 
        !           700: /*
        !           701:  * read the bad144 bad block table:
        !           702:  * call on first access to drive,
        !           703:  * or when VV was down
        !           704:  */
        !           705: 
        !           706: hprbad(hp)
        !           707: register struct hpdisk *hp;
        !           708: {
        !           709:        register struct buf *xbp, *bp;
        !           710:        register struct hptype *st;
        !           711: 
        !           712:        st = &hptype[hp->type];
        !           713:        xbp = hp->actf;
        !           714:        bp = &hpbadbuf[UNIT(xbp->b_dev)];
        !           715:        if (xbp == bp)
        !           716:                return;         /* cheap reentry protection */
        !           717:        bp->b_flags = B_BUSY|B_READ;
        !           718:        bp->b_dev = xbp->b_dev;
        !           719:        bp->b_un.b_addr = (caddr_t)&hpbad[UNIT(xbp->b_dev)];
        !           720:        bp->b_bcount = sizeof(struct bad144);
        !           721:        bp->b_resid = 0;
        !           722:        bp->b_blkno = st->ncyl * st->nspc - st->nsect;  /* fake-ish */
        !           723:        bp->b_cylin = st->ncyl - 1;
        !           724:        bp->av_forw = xbp;
        !           725:        hp->actf = bp;
        !           726:        bzero(bp->b_un.b_addr, sizeof(struct bad144));
        !           727: }
        !           728: 
        !           729: /*
        !           730:  * here when a bad block is detected:
        !           731:  * find the replacement block, and restart transfer for it
        !           732:  */
        !           733: hpbadrep(hp, mbbc)
        !           734: register struct hpdisk *hp;
        !           735: int mbbc;
        !           736: {
        !           737:        register daddr_t bno;
        !           738:        register struct hptype *st;
        !           739:        struct buf *bp;
        !           740:        register int i;
        !           741: 
        !           742:        if (hp->flags & UREVEC)
        !           743:                return (0);
        !           744:        st = &hptype[hp->type];
        !           745:        bp = hp->actf;
        !           746:        hp->badsec = (bp->b_bcount - mbbc) / SECTOR;
        !           747:        bno = bp->b_cylin * st->nspc + bp->b_blkno % st->nspc;  /* true lbn */
        !           748:        bno += hp->badsec;
        !           749:        i = bno / st->nspc;
        !           750:        bno %= st->nspc;
        !           751:        i = bad144rep(&hpbad[UNIT(bp->b_dev)], i, (int)bno/st->nsect, (int)bno%st->nsect);
        !           752:        if (i < 0)
        !           753:                return (0);
        !           754:        bno = st->ncyl*st->nspc - st->nsect - 1 - i;
        !           755:        hp->addr->hpcs1 = HP_DCLR|HP_GO;
        !           756:        if (mbbc > SECTOR)
        !           757:                mbbc = SECTOR;
        !           758:        hpcontin(hp, bno, hp->badsec*SECTOR, mbbc);
        !           759:        hp->flags |= UREVEC;
        !           760:        return (1);
        !           761: }
        !           762: 
        !           763: /*
        !           764:  * here after replacing the bad block:
        !           765:  * now do the rest of the original transfer
        !           766:  */
        !           767: hpbadcont(hp)
        !           768: register struct hpdisk *hp;
        !           769: {
        !           770:        register struct buf *bp;
        !           771:        int next, resid;
        !           772:        daddr_t bno;
        !           773:        int nspc;
        !           774: 
        !           775:        hp->flags &=~ UREVEC;
        !           776:        bp = hp->actf;
        !           777:        next = (hp->badsec + 1) * SECTOR;
        !           778:        resid = bp->b_bcount - next;
        !           779:        if (resid <= 0)
        !           780:                return (0);
        !           781:        nspc = hptype[hp->type].nspc;
        !           782:        bno = bp->b_cylin*nspc + bp->b_blkno%nspc;
        !           783:        bno += hp->badsec + 1;
        !           784:        hpcontin(hp, bno, next, resid);
        !           785:        return (1);
        !           786: }
        !           787: 
        !           788: /*
        !           789:  * correct an ECC error and restart the transfer
        !           790:  * the error is (hpec1-1) bits into the current sector;
        !           791:  * at that point, the bits set in hpec2 are wrong.
        !           792:  */
        !           793: hpecc(hp, bc)
        !           794: register struct hpdisk *hp;
        !           795: int bc;
        !           796: {
        !           797:        register struct hpdevice *reg;
        !           798:        register struct buf *bp;
        !           799:        register int i;
        !           800:        int nxf;
        !           801:        unsigned int mask;
        !           802:        long a, lasta;
        !           803:        struct mbaddr *ap;
        !           804:        register daddr_t bno;
        !           805:        register struct hptype *st;
        !           806: 
        !           807:        if ((bp = hp->actf) == NULL)
        !           808:                panic("hpecc");
        !           809:        reg = hp->addr;
        !           810:        ap = &hpaddr[UNIT(bp->b_dev)];
        !           811:        lasta = mbcuraddr(ap);
        !           812:        nxf = bp->b_bcount - bc;
        !           813:        i = reg->hpec1 - 1;             /* -1 makes 0 origin */
        !           814:        a = lasta - (nxf > SECTOR ? SECTOR : nxf) + ((i&~07)>>3);
        !           815:        mask = reg->hpec2;
        !           816:        mask <<= i&07;
        !           817:        for (; a < lasta && mask; mask >>= 8, a++)
        !           818:                mbputc(ap, a, mbgetc(ap, a)^mask);
        !           819:        st = &hptype[hp->type];
        !           820:        bno = bp->b_cylin*st->nspc + bp->b_blkno%st->nspc + nxf/SECTOR;
        !           821:        printf("hp%d: soft ecc sec %ld\n", UNIT(bp->b_dev), bno - 1);
        !           822:        if (bc == 0)
        !           823:                return (0);
        !           824:        reg->hpcs1 = HP_DCLR|HP_GO;
        !           825:        hpcontin(hp, bno, bp->b_bcount - bc, bc);
        !           826:        return (1);
        !           827: }
        !           828: 
        !           829: /*
        !           830:  * continue the current transfer,
        !           831:  * which was interrupted:
        !           832:  * move size bytes to or from the current buffer at offset off,
        !           833:  * starting with disk sector bno
        !           834:  * used for bad sector replacement,
        !           835:  * and to continue after bad sectors or ECC correction
        !           836:  */
        !           837: hpcontin(hp, bno, off, size)
        !           838: register struct hpdisk *hp;
        !           839: daddr_t bno;
        !           840: int off, size;
        !           841: {
        !           842:        register struct hpdevice *reg;
        !           843:        struct mbaddr *ap;
        !           844:        register struct buf *bp;
        !           845:        register struct hptype *st;
        !           846: 
        !           847:        reg = hp->addr;
        !           848:        bp = hp->actf;
        !           849:        ap = &hpaddr[UNIT(bp->b_dev)];
        !           850:        st = &hptype[hp->type];
        !           851:        mbadj(ap, off, size);
        !           852:        reg->hpdc = bno / st->nspc;
        !           853:        bno %= st->nspc;
        !           854:        reg->hpda = ((bno/st->nsect)<<8) | (bno%st->nsect);
        !           855:        mbcontin(ap);
        !           856:        if (bp->b_flags & B_READ)
        !           857:                reg->hpcs1 = HP_RCOM|HP_GO;
        !           858:        else
        !           859:                reg->hpcs1 = HP_WCOM|HP_GO;
        !           860: }
        !           861: 
        !           862: hpread(dev)
        !           863:        dev_t dev;
        !           864: {
        !           865:        physio(hpstrategy, &hpbuf[UNIT(dev)], dev, B_READ, minphys);
        !           866: }
        !           867: 
        !           868: hpwrite(dev)
        !           869:        dev_t dev;
        !           870: {
        !           871:        physio(hpstrategy, &hpbuf[UNIT(dev)], dev, B_WRITE, minphys);
        !           872: }
        !           873: 
        !           874: hpioctl(dev, cmd, addr, flag)
        !           875: dev_t dev;
        !           876: int cmd;
        !           877: caddr_t addr;
        !           878: int flag;
        !           879: {
        !           880:        register struct hpdisk *hp;
        !           881:        long parts[2];
        !           882: 
        !           883:        hp = &hpdisk[UNIT(dev)];
        !           884:        switch (cmd) {
        !           885:        case DIOSSIZ:
        !           886:                if ((flag & FWRITE) == 0) {
        !           887:                        u.u_error = EBADF;
        !           888:                        return;
        !           889:                }
        !           890:                if (copyin(addr, (caddr_t)parts, sizeof(parts)) < 0) {
        !           891:                        u.u_error = EFAULT;
        !           892:                        return;
        !           893:                }
        !           894:                /*
        !           895:                 * why test this?  see comments above hpstrategy
        !           896:                 */
        !           897:                if ((parts[0] % hptype[hp->type].nspc) != 0) {
        !           898:                        u.u_error = EINVAL;
        !           899:                        return;
        !           900:                }
        !           901:                hp->blkoff[PART(dev)] = parts[0];
        !           902:                hp->nblocks[PART(dev)] = parts[1];
        !           903:                return;
        !           904: 
        !           905:        case DIOGSIZ:
        !           906:                parts[0] = hp->blkoff[PART(dev)];
        !           907:                parts[1] = hp->nblocks[PART(dev)];
        !           908:                if (copyout((caddr_t)parts, addr, sizeof(parts)) < 0)
        !           909:                        u.u_error = EFAULT;
        !           910:                return;
        !           911: 
        !           912:        default:
        !           913:                u.u_error = ENOTTY;
        !           914:                return;
        !           915:        }
        !           916: }
        !           917: 
        !           918: /*
        !           919:  * check for offline drives and hung controllers
        !           920:  */
        !           921: 
        !           922: hpwatch()
        !           923: {
        !           924:        register struct hpdisk *hp;
        !           925:        register struct hpdevice *reg;
        !           926:        register struct buf *bp;
        !           927:        register int s;
        !           928: 
        !           929:        s = spl6();
        !           930:        timeout(hpwatch, (caddr_t)0, 15*HZ);
        !           931:        for (hp = &hpdisk[hpcnt-1]; hp >= hpdisk; hp--) {
        !           932:                if ((hp->flags & UWOL) == 0 || (reg = hp->addr) == 0)
        !           933:                        continue;
        !           934:                if ((reg->hpds & (HPDS_DPR|HPDS_MOL)) != (HPDS_DPR|HPDS_MOL)) {
        !           935:                        if ((hp->flags & UWAITOL) == 0) {
        !           936:                                hp->flags |= UWAITOL;
        !           937:                                continue;
        !           938:                        }
        !           939:                        printf("hp%d offline\n", hp - hpdisk);
        !           940:                        while ((bp = hp->actf) != NULL) {
        !           941:                                bp->b_flags |= B_ERROR;
        !           942:                                hp->actf = bp->av_forw;
        !           943:                                iodone(bp);
        !           944:                        }
        !           945:                }
        !           946:                hp->flags &=~ (UWAITOL|UWOL);
        !           947:                hpustart(hp);
        !           948:        }
        !           949:        splx(s);
        !           950: }

unix.superglobalmegacorp.com

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