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

unix.superglobalmegacorp.com

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