Annotation of researchv10dc/lsys/io/up.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * UNIBUS SMD disk driver
                      3:  *
                      4:  * undone:
                      5:  *     Add bad sector forwarding code
                      6:  *     Check that offset recovery code works
                      7:  *     unibus mapping is suboptimal; if the queue gets long,
                      8:  *     buffered data paths will be underused
                      9:  */
                     10: 
                     11: #include "sys/param.h"
                     12: #include "sys/buf.h"
                     13: #include "sys/conf.h"
                     14: #include "sys/user.h"
                     15: #include "sys/up.h"
                     16: #include "sys/ubaddr.h"
                     17: #include "sys/subaddr.h"
                     18: 
                     19: #define        NOUPSEEK        1       /* because emulex doesn't do it right */
                     20: 
                     21: /*
                     22:  * hardware registers
                     23:  */
                     24: 
                     25: struct updevice
                     26: {
                     27:        u_short upcs1;          /* control and status register 1 */
                     28:        short   upwc;           /* word count register */
                     29:        u_short upba;           /* UNIBUS address register */
                     30:        u_short upda;           /* desired address register */
                     31:        u_short upcs2;          /* control and status register 2 */
                     32:        u_short upds;           /* drive status */
                     33:        u_short uper1;          /* error register 1 */
                     34:        u_short upas;           /* attention summary */
                     35:        u_short upla;           /* look ahead */
                     36:        u_short updb;           /* data buffer */
                     37:        u_short upmr;           /* maintenance */ 
                     38:        u_short updt;           /* drive type */
                     39:        u_short upsn;           /* serial number */
                     40:        u_short upof;           /* offset register */
                     41:        u_short updc;           /* desired cylinder address register */
                     42:        u_short uphr;           /* holding register */
                     43:        u_short upmr2;          /* maintenance register 2 */
                     44:        u_short uper2;          /* error register 2 */
                     45:        u_short upec1;          /* burst error bit position */
                     46:        u_short upec2;          /* burst error bit pattern */
                     47: };
                     48: 
                     49: /*
                     50:  * upcs1
                     51:  */
                     52: 
                     53: #define        UP_SC   0100000         /* special condition */
                     54: #define        UP_TRE  0040000         /* transfer error */
                     55: #define        UP_IE   0000100         /* interrupt enable */
                     56: #define        UP_GO   0000001
                     57: 
                     58: #define        UP_SEEK         004             /* seek */
                     59: #define        UP_RECAL        006             /* recalibrate */
                     60: #define        UP_DCLR         010             /* drive clear */
                     61: #define        UP_OFFSET       014             /* offset */
                     62: #define        UP_RTC          016             /* return to center-line */
                     63: #define        UP_PRESET       020             /* read-in preset */
                     64: #define        UP_SEARCH       030             /* search */
                     65: #define        UP_WCOM         060             /* write */
                     66: #define        UP_RCOM         070             /* read data */
                     67: 
                     68: /*
                     69:  * upcs2
                     70:  */
                     71: #define        UPCS2_NED       0010000         /* nonexistent drive */
                     72: #define        UPCS2_CLR       0000040         /* controller clear */
                     73: #define        UPCS2_SEL       0000007         /* unit select */
                     74: 
                     75: /*
                     76:  * upds
                     77:  */
                     78: #define        UPDS_ERR        0040000         /* composite drive error */
                     79: #define        UPDS_PIP        0020000         /* positioning in progress */
                     80: #define        UPDS_MOL        0010000         /* medium on line */
                     81: #define        UPDS_DPR        0000400         /* drive present */
                     82: #define        UPDS_DRY        0000200         /* drive ready */
                     83: #define        UPDS_VV         0000100         /* volume valid */
                     84: #define        UPDS_DREADY     (UPDS_DPR|UPDS_DRY|UPDS_MOL|UPDS_VV)
                     85: 
                     86: /*
                     87:  * uper1
                     88:  */
                     89: #define        UPER1_DCK       0100000         /* data check */
                     90: #define        UPER1_WLE       0004000         /* write lock error */
                     91: #define        UPER1_ECH       0000100         /* ecc hard error */
                     92: 
                     93: /*
                     94:  * uphr: emulex hack
                     95:  */
                     96: #define        UPHR_MAXCYL     0100027         /* max cyl address */
                     97: #define        UPHR_MAXTRAK    0100030         /* max track address */
                     98: #define        UPHR_MAXSECT    0100031         /* max sector address */
                     99: 
                    100: /*
                    101:  * upof
                    102:  */
                    103: #define        UPOF_FMT22      0010000         /* 16 bit format */
                    104: /* THE SC21 ACTUALLY JUST IMPLEMENTS ADVANCE/RETARD... */
                    105: #define        UPOF_P400       0020            /*  +400 uinches */
                    106: #define        UPOF_M400       0220            /*  -400 uinches */
                    107: #define        UPOF_P800       0040            /*  +800 uinches */
                    108: #define        UPOF_M800       0240            /*  -800 uinches */
                    109: #define        UPOF_P1200      0060            /* +1200 uinches */
                    110: #define        UPOF_M1200      0260            /* -1200 uinches */
                    111: 
                    112: #define        SECTOR  512     /* size of a hardware sector */
                    113: 
                    114: /*
                    115:  * monstrous size tables
                    116:  * one per type of drive
                    117:  */
                    118: struct size
                    119: {
                    120:        daddr_t nblocks;
                    121:        int     cyloff;
                    122: } up_sizes[8] = {
                    123:        15884,  0,              /* A=cyl 0 thru 26 */
                    124:        33440,  27,             /* B=cyl 27 thru 81 */
                    125:        495520, 0,              /* C=cyl 0 thru 814 */
                    126:        15884,  562,            /* D=cyl 562 thru 588 */
                    127:        55936,  589,            /* E=cyl 589 thru 680 */
                    128: #ifndef NOBADSECT
                    129:        81376,  681,            /* F=cyl 681 thru 814 */
                    130:        153728, 562,            /* G=cyl 562 thru 814 */
                    131: #else
                    132:        81472,  681,
                    133:        153824, 562,
                    134: #endif
                    135:        291346, 82,             /* H=cyl 82 thru 561 */
                    136: }, fj_sizes[8] = {
                    137:        10240,  0,              /* A=cyl 0 thru 31 */
                    138:        20480,  32,             /* B=cyl 32 thru 95 */
                    139:        232640, 96,             /* C=cyl 96 thru 822 */
                    140:        0,      0,
                    141:        0,      0,
                    142:        0,      0,
                    143:        0,      0,
                    144: #ifndef NOBADSECT
                    145:        0,      0,              /* H=cyl 155 thru 822 */
                    146: #else
                    147:        0,      0,
                    148: #endif
                    149: }, fj3_sizes[8] = {
                    150:        10240,  0,              /* A=cyl 0 thru 19 */
                    151:        20480,  20,             /* B=cyl 20 thru 59 */
                    152:        246784, 60,             /* C=cyl 60 thru 541 */
                    153:        246784, 542,            /* D=cyl 542 thru 1024 */
                    154:        0,      0,
                    155:        0,      0,
                    156:        0,      0,
                    157: #ifndef NOBADSECT
                    158:        0,      0,              /* H=cyl 155 thru 822 */
                    159: #else
                    160:        0,      0,
                    161: #endif
                    162: }, cd_sizes[8] = {
                    163:        10240,  0,              /* A=cyl 0 thru 63 */
                    164:        20480,  64,             /* B=cyl 64 thru 191 */
                    165:        100960, 192,            /* C=cyl 192 thru 822 */
                    166:        0,      0,
                    167:        0,      0,
                    168:        0,      0,
                    169:        0,      0,
                    170: #ifndef NOBADSECT
                    171:        100960, 0,              /* H=cyl 0 thru 630 */
                    172: #else
                    173:        100960, 0,
                    174: #endif
                    175: }, fj1_sizes[8] = {
                    176:        1024,   0,              /* cyl 0 through 3 */
                    177:        0,      0,
                    178:        0,      0,
                    179:        0,      0,
                    180:        0,      0,
                    181:        0,      0,
                    182:        0,      0,
                    183:        0,      0,
                    184: };
                    185: 
                    186: /*
                    187:  * tables of per-drive info, mostly sizes of things
                    188:  * indexed by magic numbers; see uputype
                    189:  */
                    190: struct upst upst[] = {
                    191:        32, 19, 3, 4,   32*19,  823,    up_sizes,       /* 9300/cdc */
                    192: /* 9300 actually has 815 cylinders... */
                    193:        32, 10, 3, 4,   32*10,  823,    fj_sizes,       /* fujitsu 160m */
                    194:        32, 5,  3, 4,   32*5,   631,    cd_sizes,       /* CDC 76 MB */
                    195:        32, 8,  3, 4,   32*8,   4,      fj1_sizes,      /* Fixed part of FJ */
                    196:        32, 16, 3, 4,   32*16,  1024,   fj3_sizes,      /* fujitsu 330m */
                    197: };
                    198: 
                    199: u_char up_offset[16] = {
                    200:     UPOF_P400, UPOF_M400, UPOF_P400, UPOF_M400,
                    201:     UPOF_P800, UPOF_M800, UPOF_P800, UPOF_M800, 
                    202:     UPOF_P1200, UPOF_M1200, UPOF_P1200, UPOF_M1200,
                    203:     0, 0, 0, 0
                    204: };
                    205: 
                    206: /*
                    207:  * things from config
                    208:  */
                    209: extern int upcnt, sccnt;
                    210: extern struct ubaddr scaddr[];
                    211: extern struct subaddr upaddr[];
                    212: extern struct scctl scctl[];
                    213: extern struct updisk updisk[];
                    214: extern struct buf upbuf[];
                    215: 
                    216: /*
                    217:  * controller flags, scctl.flags
                    218:  */
                    219: 
                    220: #define        CACTIVE 01      /* xfer in progress */
                    221: #define        CWAITING 02     /* xfering and timer has ticked */
                    222: 
                    223: /*
                    224:  * unit flags, updisk.flags
                    225:  */
                    226: 
                    227: #define        UACTIVE 01      /* working on this xfer */
                    228: #define        URXFR   02      /* done with any seeking; ready to roll */
                    229: #define        UWOL    04      /* waiting for offline drive */
                    230: #define        UWAITOL 010     /* waiting and timer has ticked */
                    231: 
                    232: /*
                    233:  * device number
                    234:  */
                    235: 
                    236: #define        UNIT(d) ((minor(d)>>3) & 07)
                    237: #define        PART(d) (minor(d) & 07)
                    238: 
                    239: /*
                    240:  * abuse of spare bits of struct buf
                    241:  */
                    242: #define        b_cylin b_resid         /* for disksort */
                    243: #define        b_ubm   av_back         /* this buffer's map */
                    244: 
                    245: int    upwstart, upwatch();            /* Have started guardian */
                    246: int    upwaitdry;
                    247: 
                    248: int upopen(), upstrategy(), upread(), upwrite();
                    249: 
                    250: struct cdevsw upcdev = cdinit(upopen, nulldev, upread, upwrite, nodev);
                    251: 
                    252: struct bdevsw upbdev = bdinit(upopen, nulldev, upstrategy, 0);
                    253: 
                    254: upopen(dev, flag)
                    255: int dev, flag;
                    256: {
                    257:        if (upuinit(UNIT(dev)) == 0)
                    258:                u.u_error = ENXIO;
                    259: }
                    260: 
                    261: upuinit(unit)
                    262: register int unit;
                    263: {
                    264:        register struct updevice *reg;
                    265:        register struct updisk *up;
                    266:        register struct subaddr *ua;
                    267: 
                    268:        if (unit < 0 || unit > upcnt)
                    269:                return (0);
                    270:        ua = &upaddr[unit];
                    271:        if (ua->ctl < 0)
                    272:                return (0);
                    273:        up = &updisk[unit];
                    274:        if (up->ctl)
                    275:                return (1);
                    276:        if (upcinit(ua->ctl) == 0)
                    277:                return (0);
                    278:        reg = scctl[ua->ctl].addr;
                    279:        if ((up->type = uputype(reg, ua->unit)) < 0) {
                    280:                printf("up%d absent or bad type\n", unit);
                    281:                return (0);
                    282:        }
                    283:        up->unit = ua->unit;
                    284:        up->ctl = &scctl[ua->ctl];
                    285:        up->ctl->drives[ua->unit] = up;
                    286:        return (1);
                    287: }
                    288:        
                    289: 
                    290: /*
                    291:  * determine drive type
                    292:  * very emulex dependent; should look at drive type register too.
                    293:  * perhaps there should be a way to change it?
                    294:  * this is called by updump too;
                    295:  * be prepared to run without memory management
                    296:  * unit is the hardware unit
                    297:  * return is an index into upst
                    298:  */
                    299: int
                    300: uputype(reg, unit)
                    301: register struct updevice *reg;
                    302: int unit;
                    303: {
                    304: 
                    305:        reg->upcs1 = 0;         /* conservative */
                    306:        reg->upcs2 = unit;
                    307:        if (reg->upcs2&UPCS2_NED) {
                    308:                reg->upcs1 = UP_DCLR|UP_GO;
                    309:                return (-1);
                    310:        }
                    311:        reg->uphr = UPHR_MAXTRAK;
                    312:        switch (reg->uphr) {
                    313:        default:
                    314:                reg->upcs1 = UP_DCLR|UP_GO;
                    315:                return (-1);
                    316:        case 9:
                    317:                return (unit >= 4 ? 3 : 1);             /* fujitsu hack */
                    318:        case 4:
                    319:                return (2);             /* CDC 76MB hack */
                    320:        case 7:
                    321:                return (3);             /* Fixed Fujitsu hack */
                    322:        case 15:
                    323:                return (4);             /* fuji 330m hack */
                    324:        case 19:
                    325:                return (0);             /* CDC 300 MB hack */
                    326:        }
                    327: }
                    328: 
                    329: upcinit(ctl)
                    330: int ctl;
                    331: {
                    332:        register struct scctl *sc;
                    333:        register struct updevice *reg;
                    334: 
                    335:        if (ctl < 0 || ctl >= sccnt)
                    336:                return (0);
                    337:        sc = &scctl[ctl];
                    338:        if (sc->addr)
                    339:                return (1);
                    340:        if ((reg = (struct updevice *)ubaddr(&scaddr[ctl])) == 0
                    341:        ||  ubbadaddr(scaddr[ctl].ubno, &reg->upcs1, sizeof(short))) {
                    342:                printf("sc%d absent\n", ctl);
                    343:                return (0);
                    344:        }
                    345:        reg->upcs2 = UPCS2_CLR;
                    346:        sc->addr = reg;
                    347:        sc->ubno = scaddr[ctl].ubno;
                    348:        if (upwstart == 0) {
                    349:                timeout(upwatch, (caddr_t)0, HZ);
                    350:                upwstart++;
                    351:        }
                    352:        return (1);
                    353: }
                    354:  
                    355: upstrategy(bp)
                    356:        register struct buf *bp;
                    357: {
                    358:        register struct updisk *up;
                    359:        register struct upst *st;
                    360:        register int unit;
                    361:        register int part;
                    362:        long sz;
                    363:        int s;
                    364: 
                    365:        sz = (bp->b_bcount+SECTOR-1)/SECTOR;
                    366:        unit = UNIT(bp->b_dev);
                    367:        up = &updisk[unit];
                    368:        if (up->ctl == 0) {
                    369:                bp->b_flags |= B_ERROR;
                    370:                iodone(bp);
                    371:                return;
                    372:        }
                    373:        st = &upst[up->type];
                    374:        part = PART(bp->b_dev);
                    375:        if (bp->b_blkno < 0 || bp->b_blkno+sz > st->sizes[part].nblocks) {
                    376:                if (bp->b_blkno == st->sizes[part].nblocks)
                    377:                        bp->b_resid = bp->b_bcount;
                    378:                else {  /* partial read too hard for now */
                    379:                        bp->b_error = ENXIO;
                    380:                        bp->b_flags |= B_ERROR;
                    381:                }
                    382:                iodone(bp);
                    383:                return;
                    384:        }
                    385:        bp->b_cylin = bp->b_blkno/st->nspc + st->sizes[part].cyloff;
                    386:        bp->b_ubm = (struct buf *)ubmbuf(up->ctl->ubno, bp, USLP);
                    387:        s = spl6();
                    388:        disksort(&up->actf, &up->actl, bp);
                    389:        if ((up->flags & UACTIVE) == 0) {
                    390:                upustart(up);
                    391:                if (up->ctl->actf && (up->ctl->flags & CACTIVE) == 0)
                    392:                        upstart(up->ctl);
                    393:        }
                    394:        splx(s);
                    395: }
                    396: 
                    397: /*
                    398:  * unit start:
                    399:  * if there's a block for this drive, start seeking there
                    400:  *
                    401:  * up->upcs = UP_IE cancels a pending command in the SC21
                    402:  * why not up->cs |= UP_IE?
                    403:  */
                    404: upustart(up)
                    405: register struct updisk *up;
                    406: {
                    407:        register struct buf *bp;
                    408:        register struct updevice *reg;
                    409:        register struct scctl *sc;
                    410:        register struct upst *st;
                    411:        int sn, csn;
                    412:        int didie = 0;
                    413: 
                    414:        sc = up->ctl;
                    415:        if ((bp = up->actf) == NULL)
                    416:                return (0);
                    417: #ifndef NOUPSEEK
                    418:        if (sc->flags & CACTIVE) {      /* can't start seek till xfer done */
                    419:                sc->softas |= 1<<up->unit;
                    420:                return (0);
                    421:        }
                    422: #endif
                    423:        reg = sc->addr;
                    424:        reg->upcs2 = up->unit;
                    425:        if ((reg->upds & UPDS_VV) == 0) {
                    426:                reg->upcs1 = UP_IE|UP_DCLR|UP_GO;
                    427:                reg->upcs1 = UP_IE|UP_PRESET|UP_GO;
                    428:                reg->upof = UPOF_FMT22;
                    429:                didie = 1;
                    430:        }
                    431:        if ((reg->upds & (UPDS_DPR|UPDS_MOL)) != (UPDS_DPR|UPDS_MOL)) {
                    432:                up->flags |= UWOL;
                    433:                return (didie);
                    434:        }
                    435:        if ((up->flags & UACTIVE) == 0) {       /* start seek if didn't already */
                    436:                up->flags |= UACTIVE;
                    437: #ifndef NOUPSEEK
                    438:                st = &upst[up->type];
                    439:                sn = bp->b_blkno%st->nspc;
                    440:                sn = (sn + st->nsect - st->sdist) % st->nsect;  /* sector to seek to */
                    441:                csn = sn - (reg->upla>>6);
                    442:                if (csn < 0)
                    443:                        csn += st->nsect;
                    444:                if (bp->b_cylin != reg->updc    /* seek if off cylinder */
                    445:                ||  csn > st->rdist) {          /* or not close enough */
                    446:                        reg->updc = bp->b_cylin;
                    447:                        reg->upda = sn;
                    448:                        reg->upcs1 = UP_IE|UP_SEARCH|UP_GO;
                    449:                        return (1);
                    450:                }
                    451: #endif
                    452:        }
                    453:        if ((up->flags & URXFR) == 0) { /* seek done, put on ctl queue */
                    454:                up->next = NULL;
                    455:                if (sc->actf == NULL)
                    456:                        sc->actf = up;
                    457:                else
                    458:                        sc->actl->next = up;
                    459:                sc->actl = up;
                    460:                up->flags |= URXFR;
                    461:        }
                    462:        return (didie);
                    463: }
                    464: 
                    465: /*
                    466:  * Start up a transfer on a drive.
                    467:  */
                    468: upstart(sc)
                    469: register struct scctl *sc;
                    470: {
                    471:        register struct buf *bp;
                    472:        register struct updisk *up;
                    473:        register struct updevice *reg;
                    474:        register struct upst *st;
                    475:        register c;
                    476:        uaddr_t uad;
                    477:        int sn, tn;
                    478: 
                    479: loop:
                    480:        if ((up = sc->actf) == NULL)
                    481:                return (0);
                    482:        if ((bp = up->actf) == NULL) {
                    483:                sc->actf = up->next;
                    484:                goto loop;
                    485:        }
                    486:        sc->flags |= CACTIVE;
                    487:        st = &upst[up->type];
                    488:        sn = bp->b_blkno%st->nspc;
                    489:        tn = sn/st->nsect;
                    490:        sn %= st->nsect;
                    491:        reg = sc->addr;
                    492:        reg->upcs2 = up->unit;
                    493:        c = 0;
                    494:        while ((reg->upds&UPDS_DRY) == 0) {
                    495:                if (++c > 512)
                    496:                        break;
                    497:                upwaitdry++;
                    498:        }
                    499:        if ((reg->upds & UPDS_DREADY) != UPDS_DREADY) {
                    500:                printf("up%d: not ready", UNIT(bp->b_dev));
                    501:                if ((reg->upds & UPDS_DREADY) != UPDS_DREADY) {
                    502:                        printf("\n");
                    503:                        sc->flags &=~ (CACTIVE|CWAITING);
                    504:                        sc->errcnt = 0;
                    505:                        up->actf = bp->av_forw;
                    506:                        up->flags &=~ (UACTIVE|URXFR);
                    507:                        bp->b_flags |= B_ERROR;
                    508:                        iodone(bp);
                    509:                        goto loop;
                    510:                }
                    511:                printf(" (flakey)\n");  /* inscrutable */
                    512:        }
                    513:        reg->updc = bp->b_cylin;
                    514:        reg->upda = (tn << 8) + sn;
                    515:        reg->upwc = -bp->b_bcount / sizeof(short);
                    516:        if (bp->b_flags & B_READ)
                    517:                c = UP_IE|UP_RCOM|UP_GO;
                    518:        else
                    519:                c = UP_IE|UP_WCOM|UP_GO;
                    520:        bp->b_ubm = (struct buf *)ubinspath(ubmapath(sc->ubno), (ubm_t)bp->b_ubm);
                    521:        uad = ubadbuf(sc->ubno, bp, (ubm_t)bp->b_ubm);
                    522:        reg->upba = uad;
                    523:        reg->upcs1 = c|((uad>>8)&0x300);
                    524:        return (1);
                    525: }
                    526: 
                    527: /*
                    528:  * Handle a disk interrupt.
                    529:  */
                    530: sc0int(ctl)
                    531: int ctl;
                    532: {
                    533:        register struct updevice *reg;
                    534:        register struct scctl *sc;
                    535:        register struct updisk *up;
                    536:        register struct buf *bp;
                    537:        register int unit, i, as;
                    538:        int needie;
                    539: 
                    540:        if (ctl < 0 || ctl >= sccnt) {
                    541:                printf("sc%d bad intr\n");
                    542:                return;
                    543:        }
                    544:        sc = &scctl[ctl];
                    545:        if ((reg = sc->addr) == 0) {
                    546:                printf("sc%d: stray intr\n");
                    547:                return;
                    548:        }
                    549:        needie = 1;
                    550:        as = (reg->upas & 0377) | sc->softas;
                    551:        sc->softas = 0;
                    552:        if ((sc->flags & CACTIVE) == 0) {       /* must be a seek */
                    553:                if (reg->upcs1 & UP_TRE)
                    554:                        reg->upcs1 = UP_TRE;
                    555:                goto doattn;
                    556:        }
                    557:        up = sc->actf;
                    558:        bp = up->actf;
                    559:        reg->upcs2 = up->unit;
                    560:        if ((reg->upds&UPDS_ERR) || (reg->upcs1&UP_TRE)) {
                    561:                i = 0;
                    562:                while ((reg->upds & UPDS_DRY) == 0) {
                    563:                        if (++i > 512)
                    564:                                break;
                    565:                        upwaitdry++;
                    566:                }
                    567:                if (reg->uper1&UPER1_WLE) {
                    568:                        printf("up%d: write locked\n", UNIT(bp->b_dev));
                    569:                        bp->b_flags |= B_ERROR;
                    570:                } else if (++sc->errcnt > 27) {
                    571:                        harderr(bp, "up");
                    572:                        printf("cs2=%o er1=%o er2=%o\n",
                    573:                            reg->upcs2&0177777, reg->uper1&0177777, reg->uper2&0177777);
                    574:                        bp->b_flags |= B_ERROR;
                    575:                } else {
                    576:                        /*
                    577:                         * soft ecc, try to correct
                    578:                         */
                    579:                        sc->flags &=~ (CACTIVE|CWAITING);        /* force retry */
                    580:                        if ((reg->uper1&(UPER1_DCK|UPER1_ECH))==UPER1_DCK)
                    581:                                if (upecc(up))
                    582:                                        return; /* probably wrong */
                    583:                }
                    584:                /*
                    585:                 * `hard' error. clear and try again
                    586:                 */
                    587:                reg->upcs1 = UP_TRE|UP_IE|UP_DCLR|UP_GO;
                    588:                needie = 0;
                    589:                if ((sc->errcnt&07) == 4 && (sc->flags & CACTIVE) == 0) {
                    590:                        reg->upcs1 = UP_RECAL|UP_IE|UP_GO;
                    591:                        sc->recal = 0;
                    592:                        goto nextrecal;
                    593:                }
                    594:        }
                    595:        /*
                    596:         * Advance recalibration finite state machine
                    597:         * if recalibrate in progress, through
                    598:         *      RECAL
                    599:         *      SEEK
                    600:         *      OFFSET (optional)
                    601:         *      RETRY
                    602:         */
                    603:        switch (sc->recal) {
                    604:        case 1:
                    605:                reg->updc = bp->b_cylin;
                    606:                reg->upcs1 = UP_SEEK|UP_IE|UP_GO;
                    607:                goto nextrecal;
                    608:        case 2:
                    609:                if (sc->errcnt < 16 || (bp->b_flags&B_READ) == 0)
                    610:                        goto donerecal;
                    611:                reg->upof = up_offset[sc->errcnt & 017] | UPOF_FMT22;
                    612:                reg->upcs1 = UP_IE|UP_OFFSET|UP_GO;
                    613:        nextrecal:
                    614:                sc->recal++;
                    615:                sc->flags |= CACTIVE;
                    616:                return;
                    617: 
                    618:        donerecal:
                    619:        case 3:
                    620:                sc->recal = 0;
                    621:                sc->flags &=~ CACTIVE;
                    622:                break;
                    623:        }
                    624:        if (sc->flags & CACTIVE) {      /* `active' means we're done */
                    625:                if (sc->errcnt >= 16) {
                    626:                        reg->upof = UPOF_FMT22;
                    627:                        reg->upcs1 = UP_RTC|UP_GO|UP_IE;
                    628:                        while (reg->upds & UPDS_PIP)
                    629:                                DELAY(25);
                    630:                        needie = 0;
                    631:                }
                    632:                sc->flags &=~ (CACTIVE|CWAITING);
                    633:                sc->errcnt = 0;
                    634:                sc->actf = up->next;
                    635:                up->flags &=~ (UACTIVE|URXFR);
                    636:                up->actf = bp->av_forw;
                    637:                bp->b_resid = (-reg->upwc * sizeof(short));
                    638:                ubmfree(sc->ubno, (ubm_t)bp->b_ubm);
                    639:                iodone(bp);
                    640:                if (up->actf)
                    641:                        if (upustart(up))
                    642:                                needie = 0;
                    643:        }
                    644:        as |= reg->upas;
                    645:        as &= ~(1<<up->unit);
                    646: doattn:
                    647:        /*
                    648:         * Process other units which need attention.
                    649:         */
                    650:        for (unit = 0, i = 1; unit < NSCUP && as; i <<= 1, unit++) {
                    651:                if ((as & i) == 0)
                    652:                        continue;
                    653:                as &= ~i;
                    654:                reg->upas = i;
                    655:                if ((up = sc->drives[unit]) != NULL && upustart(up))
                    656:                        needie = 0;
                    657:        }
                    658:        if (sc->actf && (sc->flags & CACTIVE) == 0)
                    659:                if (upstart(sc))
                    660:                        needie = 0;
                    661:        if (needie)
                    662:                reg->upcs1 = UP_IE;     /* why bother? */
                    663: }
                    664: 
                    665: upread(dev)
                    666:        dev_t dev;
                    667: {
                    668:        physio(upstrategy, &upbuf[UNIT(dev)], dev, B_READ, minphys);
                    669: }
                    670: 
                    671: upwrite(dev)
                    672:        dev_t dev;
                    673: {
                    674:        physio(upstrategy, &upbuf[UNIT(dev)], dev, B_WRITE, minphys);
                    675: }
                    676: 
                    677: /*
                    678:  * correct an ECC error and restart the transfer
                    679:  * the error is (upec1-1) bits into the current sector;
                    680:  * at that point, the bits set in upec2 are wrong.
                    681:  *
                    682:  * should be able just to set the GO bit and proceed,
                    683:  * but emulex insists we do DCLR first, or so the book says,
                    684:  * because DCK sets ERR in upds
                    685:  */
                    686: upecc(up)
                    687: register struct updisk *up;
                    688: {
                    689:        register struct updevice *reg;
                    690:        register struct scctl *sc;
                    691:        register struct buf *bp;
                    692:        register int i;
                    693:        int nxf;
                    694:        unsigned int mask;
                    695:        uaddr_t uad, lastua;
                    696:        int xc, xa;
                    697: 
                    698:        if ((bp = up->actf) == NULL || (sc = up->ctl) == NULL)
                    699:                panic("upecc");
                    700:        reg = sc->addr;
                    701:        ubmflush(sc->ubno, ubmpath((ubm_t)bp->b_ubm));
                    702:        lastua = reg->upba + ((reg->upcs1&0x300)<<8);
                    703:        nxf = bp->b_bcount + (reg->upwc * sizeof(short));
                    704:        i = reg->upec1 - 1;             /* -1 makes 0 origin */
                    705:        uad = lastua - (nxf > SECTOR ? SECTOR : nxf) + ((i&~07)>>3);
                    706:        mask = reg->upec2;
                    707:        mask <<= i&07;
                    708:        for (; uad < lastua && mask; mask >>= 8, uad++)
                    709:                ubputc(sc->ubno, uad, ubgetc(sc->ubno, uad)^mask);
                    710:        printf("up%d%o: soft ecc sec %ld\n", UNIT(bp->b_dev), PART(bp->b_dev),
                    711:                bp->b_blkno + nxf/SECTOR - 1);
                    712:        sc->flags |= CACTIVE;   /* either complete or continuing */
                    713:        if (reg->upwc == 0)
                    714:                return (0);
                    715: #ifdef notdef
                    716:        reg->uper1 = 0;
                    717:        reg->upcs1 |= UP_GO;
                    718: #else          /* clear wretched emulex error */
                    719:        xc = reg->updc;
                    720:        xa = reg->upda;
                    721:        /* ba, wc undisturbed by DCLR */
                    722:        reg->upcs1 = UP_TRE|UP_IE|UP_DCLR|UP_GO;
                    723:        reg->updc = xc;
                    724:        reg->upda = xa;
                    725:        reg->upba = lastua;
                    726:        i = (lastua >> 8) & 0x300;
                    727:        i |= UP_IE|UP_GO|UP_RCOM;
                    728:        reg->upcs1 = i;
                    729: #endif
                    730:        return (1);
                    731: }
                    732: 
                    733: /*
                    734:  * check for offline drives and hung controllers
                    735:  */
                    736: 
                    737: upwatch()
                    738: {
                    739:        register struct scctl *sc;
                    740:        register struct updisk *up;
                    741:        register struct updevice *reg;
                    742:        register struct buf *bp;
                    743:        register int ounit;
                    744:        register int s;
                    745: 
                    746:        s = spl6();
                    747:        timeout(upwatch, (caddr_t)0, 15*HZ);
                    748:        for (up = &updisk[upcnt-1]; up >= updisk; up--) {
                    749:                if ((up->flags & UWOL) == 0)
                    750:                        continue;
                    751:                reg = up->ctl->addr;
                    752:                ounit = reg->upcs2 & UPCS2_SEL;
                    753:                reg->upcs2 = up->unit;
                    754:                if ((reg->upds & (UPDS_DPR|UPDS_MOL)) != (UPDS_DPR|UPDS_MOL)) {
                    755:                        if ((up->flags & UWAITOL) == 0) {
                    756:                                up->flags |= UWAITOL;
                    757:                                reg->upcs2 = ounit;
                    758:                                continue;
                    759:                        }
                    760:                        printf("up%d offline\n", up - updisk);
                    761:                        while ((bp = up->actf) != NULL) {
                    762:                                bp->b_flags |= B_ERROR;
                    763:                                up->actf = bp->av_forw;
                    764:                                ubmfree(up->ctl->ubno, (ubm_t)bp->b_ubm);
                    765:                                iodone(bp);
                    766:                        }
                    767:                }
                    768:                up->flags &=~ (UWAITOL|UWOL);
                    769:                upustart(up);
                    770:                reg->upcs2 = ounit;
                    771:        }
                    772:        for (sc = &scctl[sccnt-1]; sc >= scctl; sc--) {
                    773:                if (sc->flags & CACTIVE) {
                    774:                        if ((sc->flags & CWAITING) == 0)
                    775:                                sc->flags |= CWAITING;
                    776:                        else {
                    777:                                sc->addr->upcs2 = UPCS2_CLR;
                    778:                                printf("sc%d hung, kicked\n", sc - scctl);
                    779:                                sc->flags &=~ (CWAITING|CACTIVE);
                    780:                        }
                    781:                }
                    782:                if (sc->actf && (sc->flags & CACTIVE) == 0)
                    783:                        upstart(sc);
                    784:        }
                    785:        splx(s);
                    786: }

unix.superglobalmegacorp.com

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