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

unix.superglobalmegacorp.com

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