Annotation of researchv10no/sys/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: #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.