Annotation of 40BSD/sys/dev/up.c.SC11, revision 1.1.1.1

1.1       root        1: /*     up.c    3.28    10/21/80        */
                      2: 
                      3: #include "../conf/up.h"
                      4: /*
                      5:  * UNIBUS disk driver with overlapped seeks and ECC recovery.
                      6:  *
                      7:  * This driver works marginally on an Emulex SC-11B controller with rev
                      8:  * level J microcode, defining:
                      9:  *     int     olducode = 1;
                     10:  * to force CPU stalling delays.
                     11:  *
                     12:  * It has worked with no delays and no problems on a prototype
                     13:  * SC-21 controller.  Emulex intends to upgrade all SC-11s on VAXes to SC-21s.
                     14:  * You should get a SC-21 to replace any SC-11 on a VAX.
                     15:  *
                     16:  * SC-11B Controller switch settings:
                     17:  *     SW1-1   5/19 surfaces   (off, 19 surfaces on Ampex 9300)
                     18:  *     SW1-2   chksum enable   (off, checksum disabled)
                     19:  *     SW1-3   volume select   (off, 815 cylinders)
                     20:  *     SW1-4   sector select   (on, 32 sectors)
                     21:  *     SW1-5   unused          (off)
                     22:  *     SW1-6   port select     (on, single port)
                     23:  *     SW1-7   npr delay       (off, disable)
                     24:  *     SW1-8   ecc test mode   (off, disable)
                     25:  * and top mounted switches:
                     26:  *     SW2-1   extend opcodes  (off=open, disable)
                     27:  *     SW2-2   extend diag     (off=open, disable)
                     28:  *     SW2-3   4 wd dma burst  (on=closed, enable)
                     29:  *     SW2-4   unused          (off=open)
                     30:  */
                     31: 
                     32: #include "../h/param.h"
                     33: #include "../h/systm.h"
                     34: #include "../h/dk.h"
                     35: #include "../h/buf.h"
                     36: #include "../h/conf.h"
                     37: #include "../h/dir.h"
                     38: #include "../h/user.h"
                     39: #include "../h/map.h"
                     40: #include "../h/pte.h"
                     41: #include "../h/mba.h"
                     42: #include "../h/mtpr.h"
                     43: #include "../h/uba.h"
                     44: #include "../h/vm.h"
                     45: 
                     46: #define        ushort  unsigned short
                     47: 
                     48: struct device
                     49: {
                     50:        ushort  upcs1;          /* control and status register 1 */
                     51:        short   upwc;           /* word count register */
                     52:        ushort  upba;           /* UNIBUS address register */
                     53:        ushort  upda;           /* desired address register */
                     54:        ushort  upcs2;          /* control and status register 2 */
                     55:        ushort  upds;           /* drive Status */
                     56:        ushort  uper1;          /* error register 1 */
                     57:        ushort  upas;           /* attention summary */
                     58:        ushort  upla;           /* look ahead */
                     59:        ushort  updb;           /* data buffer */
                     60:        ushort  upmr;           /* maintenance */ 
                     61:        ushort  updt;           /* drive type */
                     62:        ushort  upsn;           /* serial number */
                     63:        ushort  upof;           /* offset register */
                     64:        ushort  updc;           /* desired cylinder address register */
                     65:        ushort  upcc;           /* current cylinder */
                     66:        ushort  uper2;          /* error register 2 */
                     67:        ushort  uper3;          /* error register 3 */
                     68:        ushort  upec1;          /* burst error bit position */
                     69:        ushort  upec2;          /* burst error bit pattern */
                     70: };
                     71: 
                     72: /*
                     73:  * Software extension to the upas register, so we can
                     74:  * postpone starting SEARCH commands until the controller
                     75:  * is not transferring.
                     76:  */
                     77: int    upsoftas;
                     78: 
                     79: /*
                     80:  * If upseek then we don't issue SEARCH commands but rather just
                     81:  * settle for a SEEK to the correct cylinder.
                     82:  */
                     83: int    upseek;
                     84: 
                     85: #define        NSECT   32
                     86: #define        NTRAC   19
                     87: 
                     88: /*
                     89:  * Constants controlling on-cylinder SEARCH usage.
                     90:  *
                     91:  *     upSDIST/2 msec          time needed to start transfer
                     92:  *     upRDIST/2 msec          tolerable rotational latency when on-cylinder
                     93:  *
                     94:  * If we are no closer than upSDIST sectors and no further than upSDIST+upRDIST
                     95:  * and in the driver then we take it as it is.  Otherwise we do a SEARCH
                     96:  * requesting an interrupt upSDIST sectors in advance.
                     97:  */
                     98: #define        _upSDIST        2               /* 1.0 msec */
                     99: #define        _upRDIST        4               /* 2.0 msec */
                    100: 
                    101: int    upSDIST = _upSDIST;
                    102: int    upRDIST = _upRDIST;
                    103: 
                    104: /*
                    105:  * To fill a 300M drive:
                    106:  *     A is designed to be used as a root.
                    107:  *     B is suitable for a swap area.
                    108:  *     H is the primary storage area.
                    109:  * On systems with RP06'es, we normally use only 291346 blocks of the H
                    110:  * area, and use DEF or G to cover the rest of the drive.  The C system
                    111:  * covers the whole drive and can be used for pack-pack copying.
                    112:  */
                    113: struct size
                    114: {
                    115:        daddr_t nblocks;
                    116:        int     cyloff;
                    117: } up_sizes[8] = {
                    118:        15884,  0,              /* A=cyl 0 thru 26 */
                    119:        33440,  27,             /* B=cyl 27 thru 81 */
                    120:        495520, 0,              /* C=cyl 0 thru 814 */
                    121:        15884,  562,            /* D=cyl 562 thru 588 */
                    122:        55936,  589,            /* E=cyl 589 thru 680 */
                    123:        81472,  681,            /* F=cyl 681 thru 814 */
                    124:        153824, 562,            /* G=cyl 562 thru 814 */
                    125:        445664, 82,             /* H=cyl 82 thru 814 */
                    126: /* Later, and more safely for H area...
                    127:        291346, 82,             /* H=cyl 82 thru 561 */
                    128: };
                    129: 
                    130: /*
                    131:  * The following defines are used in offset positioning
                    132:  * when trying to recover disk errors, with the constants being
                    133:  * +/- microinches.  Note that header compare inhibit (HCI) is not
                    134:  * tried (this makes sense only during read, in any case.)
                    135:  *
                    136:  * NOT ALL OF THESE ARE IMPLEMENTED ON 9300!?!
                    137:  */
                    138: #define        P400    020
                    139: #define        M400    0220
                    140: #define        P800    040
                    141: #define        M800    0240
                    142: #define        P1200   060
                    143: #define        M1200   0260
                    144: #define        HCI     020000
                    145: 
                    146: int    up_offset[16] =
                    147: {
                    148:        P400, M400, P400, M400,
                    149:        P800, M800, P800, M800,
                    150:        P1200, M1200, P1200, M1200,
                    151:        0, 0, 0, 0,
                    152: };
                    153: 
                    154: /*
                    155:  * Each drive has a table uputab[i].  On this table are sorted the
                    156:  * pending requests implementing an elevator algorithm (see dsort.c.)
                    157:  * In the upustart() routine, each drive is independently advanced
                    158:  * until it is on the desired cylinder for the next transfer and near
                    159:  * the desired sector.  The drive is then chained onto the uptab
                    160:  * table, and the transfer is initiated by the upstart() routine.
                    161:  * When the transfer is completed the driver reinvokes the upustart()
                    162:  * routine to set up the next transfer.
                    163:  */
                    164: struct buf     uptab;
                    165: struct buf     uputab[NUP];
                    166: 
                    167: struct buf     rupbuf;                 /* Buffer for raw i/o */
                    168: 
                    169: /* Drive commands, placed in upcs1 */
                    170: #define        GO      01              /* Go bit, set in all commands */
                    171: #define        PRESET  020             /* Preset drive at init or after errors */
                    172: #define        OFFSET  014             /* Offset heads to try to recover error */
                    173: #define        RTC     016             /* Return to center-line after OFFSET */
                    174: #define        SEARCH  030             /* Search for cylinder+sector */
                    175: #define        SEEK    04              /* Seek to cylinder */
                    176: #define        RECAL   06              /* Recalibrate, needed after seek error */
                    177: #define        DCLR    010             /* Drive clear, after error */
                    178: #define        WCOM    060             /* Write */
                    179: #define        RCOM    070             /* Read */
                    180: 
                    181: /* Other bits of upcs1 */
                    182: #define        IE      0100            /* Controller wide interrupt enable */
                    183: #define        TRE     040000          /* Transfer error */
                    184: #define        RDY     0200            /* Transfer terminated */
                    185: 
                    186: /* Drive status bits of upds */
                    187: #define        PIP     020000          /* Positioning in progress */
                    188: #define        ERR     040000          /* Error has occurred, DCLR necessary */
                    189: #define        VV      0100            /* Volume is valid, set by PRESET */
                    190: #define        DPR     0400            /* Drive has been preset */
                    191: #define        MOL     010000          /* Drive is online, heads loaded, etc */
                    192: #define        DRY     0200            /* Drive ready */
                    193: 
                    194: /* Bits of upcs2 */
                    195: #define        CLR     040             /* Controller clear */
                    196: /* Bits of uper1 */
                    197: #define        DCK     0100000         /* Ecc error occurred */
                    198: #define        ECH     0100            /* Ecc error was unrecoverable */
                    199: #define        WLE     04000           /* Attempt to write read-only drive */
                    200: 
                    201: /* Bits of upof; the offset bits above are also in this register */
                    202: #define        FMT22   010000          /* 16 bits/word, must be always set */
                    203: 
                    204: #define        b_cylin b_resid
                    205: 
                    206: int    up_ubinfo;              /* Information about UBA usage saved here */
                    207: /*
                    208:  * The EMULEX controller balks if accessed quickly after
                    209:  * certain operations.  With rev J delays seem to be needed only
                    210:  * when selecting a new unit, and in drive initialization type
                    211:  * like PRESET and DCLR.  The following variables control the delay
                    212:  * DELAY(n) is approximately n usec.
                    213:  */
                    214: int    olducode = 1;
                    215: int    idelay = 500;           /* Delay after PRESET or DCLR */
                    216: int    osdelay = 150;          /* Old delay after selecting drive in upcs2 */
                    217: int    ordelay = 100;          /* Old delay after SEARCH */
                    218: int    oasdel = 100;           /* Old delay after clearing bit in upas */
                    219: int    nsdelay = 25;
                    220: 
                    221: #define        DELAY(N)                { register int d; d = N; while (--d > 0); }
                    222:  
                    223: int    nwaitcs2;               /* How many sdelay loops ? */
                    224: int    neasycs2;               /* How many sdelay loops not needed ? */
                    225: 
                    226: int    up_wticks;              /* Ticks waiting for interrupt */
                    227: int    upwstart;               /* Have started guardian */
                    228: int    upwatch();
                    229: 
                    230: #ifdef INTRLVE
                    231: daddr_t dkblock();
                    232: #endif
                    233:  
                    234: /*
                    235:  * Queue an i/o request for a drive, checking first that it is in range.
                    236:  *
                    237:  * A unit start is issued if the drive is inactive, causing
                    238:  * a SEARCH for the correct cylinder/sector.  If the drive is
                    239:  * already nearly on the money and the controller is not transferring
                    240:  * we kick it to start the transfer.
                    241:  */
                    242: upstrategy(bp)
                    243: register struct buf *bp;
                    244: {
                    245:        register struct buf *dp;
                    246:        register unit, xunit;
                    247:        long sz, bn;
                    248: 
                    249:        if (upwstart == 0) {
                    250:                timeout((caddr_t)upwatch, 0, HZ);
                    251:                upwstart++;
                    252:        }
                    253:        xunit = minor(bp->b_dev) & 077;
                    254:        sz = bp->b_bcount;
                    255:        sz = (sz+511) >> 9;             /* transfer size in 512 byte sectors */
                    256:        unit = dkunit(bp);
                    257:        if (unit >= NUP ||
                    258:            bp->b_blkno < 0 ||
                    259:            (bn = dkblock(bp))+sz > up_sizes[xunit&07].nblocks) {
                    260:                bp->b_flags |= B_ERROR;
                    261:                iodone(bp);
                    262:                return;
                    263:        }
                    264:        if (DK_N+unit <= DK_NMAX)
                    265:                dk_mspw[DK_N+unit] = .0000020345;
                    266:        bp->b_cylin = bn/(NSECT*NTRAC) + up_sizes[xunit&07].cyloff;
                    267:        dp = &uputab[unit];
                    268:        (void) spl5();
                    269:        disksort(dp, bp);
                    270:        if (dp->b_active == 0) {
                    271:                (void) upustart(unit);
                    272:                if (uptab.b_actf && uptab.b_active == 0)
                    273:                        (void) upstart();
                    274:        }
                    275:        (void) spl0();
                    276: }
                    277: 
                    278: /*
                    279:  * Start activity on specified drive; called when drive is inactive
                    280:  * and new transfer request arrives and also when upas indicates that
                    281:  * a SEARCH command is complete.
                    282:  */
                    283: upustart(unit)
                    284: register unit;
                    285: {
                    286:        register struct buf *bp, *dp;
                    287:        register struct device *upaddr = UPADDR;
                    288:        daddr_t bn;
                    289:        int sn, cn, csn;
                    290:        int didie = 0;
                    291: 
                    292:        /*
                    293:         * Other drivers tend to say something like
                    294:         *      upaddr->upcs1 = IE;
                    295:         *      upaddr->upas = 1<<unit;
                    296:         * here, but the SC-11B will cancel a command which
                    297:         * happens to be sitting in the cs1 if you clear the go
                    298:         * bit by storing there (so the first is not safe),
                    299:         * and it also does not like being bothered with operations
                    300:         * such as clearing upas when a transfer is active (as
                    301:         * it may well be.)
                    302:         *
                    303:         * Thus we keep careful track of when we re-enable IE
                    304:         * after an interrupt and do it only if we didn't issue
                    305:         * a command which re-enabled it as a matter of course.
                    306:         * We clear bits in upas in the interrupt routine, when
                    307:         * no transfers are active.
                    308:         */
                    309:        if (unit >= NUP)
                    310:                goto out;
                    311:        if (unit+DK_N <= DK_NMAX)
                    312:                dk_busy &= ~(1<<(unit+DK_N));
                    313:        dp = &uputab[unit];
                    314:        if ((bp = dp->b_actf) == NULL)
                    315:                goto out;
                    316:        /*
                    317:         * The SC-11B doesn't start SEARCH commands when transfers are
                    318:         * in progress.  In fact, it tends to get confused when given
                    319:         * SEARCH'es during transfers, generating interrupts with neither
                    320:         * RDY nor a bit in the upas register.  Thus we defer
                    321:         * until an interrupt when a transfer is pending.
                    322:         */
                    323:        if (uptab.b_active) {
                    324:                upsoftas |= 1<<unit;
                    325:                return (0);
                    326:        }
                    327:        if (dp->b_active)
                    328:                goto done;
                    329:        dp->b_active = 1;
                    330:        if ((upaddr->upcs2 & 07) != unit) {
                    331:                upaddr->upcs2 = unit;
                    332:                DELAY(olducode ? osdelay : nsdelay);
                    333:                nwaitcs2++;
                    334:        } else
                    335:                neasycs2++;
                    336:        /*
                    337:         * If we have changed packs or just initialized,
                    338:         * then the volume will not be valid; if so, clear
                    339:         * the drive, preset it and put in 16bit/word mode.
                    340:         */
                    341:        if ((upaddr->upds & VV) == 0) {
                    342:                upaddr->upcs1 = IE|DCLR|GO;
                    343:                DELAY(idelay);
                    344:                upaddr->upcs1 = IE|PRESET|GO;
                    345:                DELAY(idelay);
                    346:                upaddr->upof = FMT22;
                    347:                didie = 1;
                    348:        }
                    349:        if ((upaddr->upds & (DPR|MOL)) != (DPR|MOL))
                    350:                goto done;
                    351:        /*
                    352:         * Do enough of the disk address decoding to determine
                    353:         * which cylinder and sector the request is on.
                    354:         * If we are on the correct cylinder and the desired sector
                    355:         * lies between upSDIST and upSDIST+upRDIST sectors ahead of us, then
                    356:         * we don't bother to SEARCH but just begin the transfer asap.
                    357:         * Otherwise ask for a interrupt upSDIST sectors ahead.
                    358:         */
                    359:        bn = dkblock(bp);
                    360:        cn = bp->b_cylin;
                    361:        sn = bn%(NSECT*NTRAC);
                    362:        sn = (sn+NSECT-upSDIST)%NSECT;
                    363: 
                    364:        if (cn - upaddr->updc)
                    365:                goto search;            /* Not on-cylinder */
                    366:        else if (upseek)
                    367:                goto done;              /* Ok just to be on-cylinder */
                    368:        csn = (upaddr->upla>>6) - sn - 1;
                    369:        if (csn < 0)
                    370:                csn += NSECT;
                    371:        if (csn > NSECT-upRDIST)
                    372:                goto done;
                    373: 
                    374: search:
                    375:        upaddr->updc = cn;
                    376:        if (upseek)
                    377:                upaddr->upcs1 = IE|SEEK|GO;
                    378:        else {
                    379:                upaddr->upda = sn;
                    380:                upaddr->upcs1 = IE|SEARCH|GO;
                    381:        }
                    382:        didie = 1;
                    383:        /*
                    384:         * Mark this unit busy.
                    385:         */
                    386:        unit += DK_N;
                    387:        if (unit <= DK_NMAX) {
                    388:                dk_busy |= 1<<unit;
                    389:                dk_seek[unit]++;
                    390:        }
                    391:        if (olducode)
                    392:                DELAY(ordelay);
                    393:        goto out;
                    394: 
                    395: done:
                    396:        /*
                    397:         * This unit is ready to go so
                    398:         * link it onto the chain of ready disks.
                    399:         */
                    400:        dp->b_forw = NULL;
                    401:        if (uptab.b_actf == NULL)
                    402:                uptab.b_actf = dp;
                    403:        else
                    404:                uptab.b_actl->b_forw = dp;
                    405:        uptab.b_actl = dp;
                    406: 
                    407: out:
                    408:        return (didie);
                    409: }
                    410: 
                    411: /*
                    412:  * Start a transfer; call from top level at spl5() or on interrupt.
                    413:  */
                    414: upstart()
                    415: {
                    416:        register struct buf *bp, *dp;
                    417:        register unit;
                    418:        register struct device *upaddr;
                    419:        daddr_t bn;
                    420:        int dn, sn, tn, cn, cmd;
                    421: 
                    422: loop:
                    423:        /*
                    424:         * Pick a drive off the queue of ready drives, and
                    425:         * perform the first transfer on its queue.
                    426:         *
                    427:         * Looping here is completely for the sake of drives which
                    428:         * are not present and on-line, for which we completely clear the
                    429:         * request queue.
                    430:         */
                    431:        if ((dp = uptab.b_actf) == NULL)
                    432:                return (0);
                    433:        if ((bp = dp->b_actf) == NULL) {
                    434:                uptab.b_actf = dp->b_forw;
                    435:                goto loop;
                    436:        }
                    437:        /*
                    438:         * Mark the controller busy, and multi-part disk address.
                    439:         * Select the unit on which the i/o is to take place.
                    440:         */
                    441:        uptab.b_active++;
                    442:        unit = minor(bp->b_dev) & 077;
                    443:        dn = dkunit(bp);
                    444:        bn = dkblock(bp);
                    445:        cn = up_sizes[unit&07].cyloff;
                    446:        cn += bn/(NSECT*NTRAC);
                    447:        sn = bn%(NSECT*NTRAC);
                    448:        tn = sn/NSECT;
                    449:        sn %= NSECT;
                    450:        upaddr = UPADDR;
                    451:        if ((upaddr->upcs2 & 07) != dn) {
                    452:                upaddr->upcs2 = dn;
                    453:                /* DELAY(sdelay);               Provided by ubasetup() */
                    454:                nwaitcs2++;
                    455:        } else
                    456:                neasycs2++;
                    457:        up_ubinfo = ubasetup(bp, 1);    /* Providing delay */
                    458:        /*
                    459:         * If drive is not present and on-line, then
                    460:         * get rid of this with an error and loop to get
                    461:         * rid of the rest of its queued requests.
                    462:         * (Then on to any other ready drives.)
                    463:         */
                    464:        if ((upaddr->upds & (DPR|MOL)) != (DPR|MOL)) {
                    465:                printf("!DPR || !MOL, unit %d, ds %o", dn, upaddr->upds);
                    466:                if ((upaddr->upds & (DPR|MOL)) != (DPR|MOL)) {
                    467:                        printf("-- hard\n");
                    468:                        uptab.b_active = 0;
                    469:                        uptab.b_errcnt = 0;
                    470:                        dp->b_actf = bp->av_forw;
                    471:                        dp->b_active = 0;
                    472:                        bp->b_flags |= B_ERROR;
                    473:                        iodone(bp);
                    474:                        /* A funny place to do this ... */
                    475:                        ubafree(up_ubinfo), up_ubinfo = 0;
                    476:                        goto loop;
                    477:                }
                    478:                printf("-- came back\n");
                    479:        }
                    480:        /*
                    481:         * If this is a retry, then with the 16'th retry we
                    482:         * begin to try offsetting the heads to recover the data.
                    483:         */
                    484:        if (uptab.b_errcnt >= 16 && (bp->b_flags&B_WRITE) == 0) {
                    485:                upaddr->upof = up_offset[uptab.b_errcnt & 017] | FMT22;
                    486:                upaddr->upcs1 = IE|OFFSET|GO;
                    487:                DELAY(idelay);
                    488:                while (upaddr->upds & PIP)
                    489:                        DELAY(25);
                    490:        }
                    491:        /*
                    492:         * Now set up the transfer, retrieving the high
                    493:         * 2 bits of the UNIBUS address from the information
                    494:         * returned by ubasetup() for the cs1 register bits 8 and 9.
                    495:         */
                    496:        upaddr->updc = cn;
                    497:        upaddr->upda = (tn << 8) + sn;
                    498:        upaddr->upba = up_ubinfo;
                    499:        upaddr->upwc = -bp->b_bcount / sizeof (short);
                    500:        cmd = (up_ubinfo >> 8) & 0x300;
                    501:        if (bp->b_flags & B_READ)
                    502:                cmd |= IE|RCOM|GO;
                    503:        else
                    504:                cmd |= IE|WCOM|GO;
                    505:        upaddr->upcs1 = cmd;
                    506:        /*
                    507:         * This is a controller busy situation.
                    508:         * Record in dk slot NUP+DK_N (after last drive)
                    509:         * unless there aren't that many slots reserved for
                    510:         * us in which case we record this as a drive busy
                    511:         * (if there is room for that).
                    512:         */
                    513:        unit = dn+DK_N;
                    514:        if (unit <= DK_NMAX) {
                    515:                dk_busy |= 1<<unit;
                    516:                dk_xfer[unit]++;
                    517:                dk_wds[unit] += bp->b_bcount>>6;
                    518:        }
                    519:        return (1);
                    520: }
                    521: 
                    522: /*
                    523:  * Handle a device interrupt.
                    524:  *
                    525:  * If the transferring drive needs attention, service it
                    526:  * retrying on error or beginning next transfer.
                    527:  * Service all other ready drives, calling ustart to transfer
                    528:  * their blocks to the ready queue in uptab, and then restart
                    529:  * the controller if there is anything to do.
                    530:  */
                    531: upintr()
                    532: {
                    533:        register struct buf *bp, *dp;
                    534:        register unit;
                    535:        register struct device *upaddr = UPADDR;
                    536:        int as = upaddr->upas & 0377;
                    537:        int oupsoftas;
                    538:        int needie = 1;
                    539: 
                    540:        (void) spl6();
                    541:        up_wticks = 0;
                    542:        if (uptab.b_active) {
                    543:                /*
                    544:                 * The drive is transferring, thus the hardware
                    545:                 * (say the designers) will only interrupt when the transfer
                    546:                 * completes; check for it anyways.
                    547:                 */
                    548:                if ((upaddr->upcs1 & RDY) == 0) {
                    549:                        printf("!RDY: cs1 %o, ds %o, wc %d\n", upaddr->upcs1,
                    550:                            upaddr->upds, upaddr->upwc);
                    551:                        printf("as=%d act %d %d %d\n", as, uptab.b_active,
                    552:                            uputab[0].b_active, uputab[1].b_active);
                    553:                }
                    554:                /*
                    555:                 * Mark drive not busy, and check for an
                    556:                 * error condition which may have resulted from the transfer.
                    557:                 */
                    558:                dp = uptab.b_actf;
                    559:                bp = dp->b_actf;
                    560:                unit = dkunit(bp);
                    561:                if (DK_N+unit <= DK_NMAX)
                    562:                        dk_busy &= ~(1<<(DK_N+unit));
                    563:                if ((upaddr->upcs2 & 07) != unit) {
                    564:                        upaddr->upcs2 = unit;
                    565:                        DELAY(olducode ? osdelay : nsdelay);
                    566:                        nwaitcs2++;
                    567:                } else
                    568:                        neasycs2++;
                    569:                if ((upaddr->upds&ERR) || (upaddr->upcs1&TRE)) {
                    570:                        /*
                    571:                         * An error occurred, indeed.  Select this unit
                    572:                         * to get at the drive status (a SEARCH may have
                    573:                         * intervened to change the selected unit), and
                    574:                         * wait for the command which caused the interrupt
                    575:                         * to complete (DRY).
                    576:                         */
                    577:                        while ((upaddr->upds & DRY) == 0)
                    578:                                DELAY(25);
                    579:                        /*
                    580:                         * After 28 retries (16 w/o servo offsets, and then
                    581:                         * 12 with servo offsets), or if we encountered
                    582:                         * an error because the drive is write-protected,
                    583:                         * give up.  Print an error message on the last 2
                    584:                         * retries before a hard failure.
                    585:                         */
                    586:                        if (++uptab.b_errcnt > 28 || upaddr->uper1&WLE)
                    587:                                bp->b_flags |= B_ERROR;
                    588:                        else
                    589:                                uptab.b_active = 0;     /* To force retry */
                    590:                        if (uptab.b_errcnt > 27)
                    591:                                deverror(bp, upaddr->upcs2, upaddr->uper1);
                    592:                        /*
                    593:                         * If this was a correctible ECC error, let upecc
                    594:                         * do the dirty work to correct it.  If upecc
                    595:                         * starts another READ for the rest of the data
                    596:                         * then it returns 1 (having set uptab.b_active).
                    597:                         * Otherwise we are done and fall through to
                    598:                         * finish up.
                    599:                         */
                    600:                        if ((upaddr->uper1&(DCK|ECH))==DCK && upecc(upaddr, bp))
                    601:                                return;
                    602:                        /*
                    603:                         * Clear the drive and, every 4 retries, recalibrate
                    604:                         * to hopefully help clear up seek positioning problems.
                    605:                         */
                    606:                        upaddr->upcs1 = TRE|IE|DCLR|GO;
                    607:                        DELAY(idelay);
                    608:                        needie = 0;
                    609:                        if ((uptab.b_errcnt&07) == 4) {
                    610:                                upaddr->upcs1 = RECAL|GO|IE;
                    611:                                DELAY(idelay);
                    612:                                while(upaddr->upds & PIP)
                    613:                                        DELAY(25);
                    614:                        }
                    615:                }
                    616:                /*
                    617:                 * If we are still noted as active, then no
                    618:                 * (further) retries are necessary.  
                    619:                 *
                    620:                 * Make sure the correct unit is selected,
                    621:                 * return it to centerline if necessary, and mark
                    622:                 * this i/o complete, starting the next transfer
                    623:                 * on this drive with the upustart routine (if any).
                    624:                 */
                    625:                if (uptab.b_active) {
                    626:                        if (uptab.b_errcnt >= 16) {
                    627:                                upaddr->upcs1 = RTC|GO|IE;
                    628:                                DELAY(idelay);
                    629:                                while (upaddr->upds & PIP)
                    630:                                        DELAY(25);
                    631:                                needie = 0;
                    632:                        }
                    633:                        uptab.b_active = 0;
                    634:                        uptab.b_errcnt = 0;
                    635:                        uptab.b_actf = dp->b_forw;
                    636:                        dp->b_active = 0;
                    637:                        dp->b_errcnt = 0;
                    638:                        dp->b_actf = bp->av_forw;
                    639:                        bp->b_resid = (-upaddr->upwc * sizeof(short));
                    640:                        if (bp->b_resid)
                    641:                                printf("resid %d ds %o er? %o %o %o\n",
                    642:                                    bp->b_resid, upaddr->upds,
                    643:                                    upaddr->uper1, upaddr->uper2, upaddr->uper3);
                    644:                        iodone(bp);
                    645:                        if(dp->b_actf)
                    646:                                if (upustart(unit))
                    647:                                        needie = 0;
                    648:                }
                    649:                as &= ~(1<<unit);
                    650:                upsoftas &= ~(1<<unit);
                    651:                ubafree(up_ubinfo), up_ubinfo = 0;
                    652:        } else {
                    653:                if (upaddr->upcs1 & TRE) {
                    654:                        upaddr->upcs1 = TRE;
                    655:                        DELAY(idelay);
                    656:                }
                    657:        }
                    658:        /*
                    659:         * If we have a unit with an outstanding SEARCH,
                    660:         * and the hardware indicates the unit requires attention,
                    661:         * the bring the drive to the ready queue.
                    662:         * Finally, if the controller is not transferring
                    663:         * start it if any drives are now ready to transfer.
                    664:         */
                    665:        as |= upsoftas;
                    666:        oupsoftas = upsoftas;
                    667:        upsoftas = 0;
                    668:        for (unit = 0; unit < NUP; unit++)
                    669:                if ((as|oupsoftas) & (1<<unit)) {
                    670:                        if (as & (1<<unit)) {
                    671:                                upaddr->upas = 1<<unit;
                    672:                                if (olducode)
                    673:                                        DELAY(oasdel);
                    674:                        }
                    675:                        if (upustart(unit))
                    676:                                needie = 0;
                    677:                }
                    678:        if (uptab.b_actf && uptab.b_active == 0)
                    679:                if (upstart())
                    680:                        needie = 0;
                    681: out:
                    682:        if (needie)
                    683:                upaddr->upcs1 = IE;
                    684: }
                    685: 
                    686: upread(dev)
                    687: {
                    688: 
                    689:        physio(upstrategy, &rupbuf, dev, B_READ, minphys);
                    690: }
                    691: 
                    692: upwrite(dev)
                    693: {
                    694: 
                    695:        physio(upstrategy, &rupbuf, dev, B_WRITE, minphys);
                    696: }
                    697: 
                    698: /*
                    699:  * Correct an ECC error, and restart the i/o to complete
                    700:  * the transfer if necessary.  This is quite complicated because
                    701:  * the transfer may be going to an odd memory address base and/or
                    702:  * across a page boundary.
                    703:  */
                    704: upecc(up, bp)
                    705: register struct device *up;
                    706: register struct buf *bp;
                    707: {
                    708:        struct uba_regs *ubp = (struct uba_regs *)UBA0;
                    709:        register int i;
                    710:        caddr_t addr;
                    711:        int reg, bit, byte, npf, mask, o, cmd, ubaddr;
                    712:        int bn, cn, tn, sn;
                    713: 
                    714:        /*
                    715:         * Npf is the number of sectors transferred before the sector
                    716:         * containing the ECC error, and reg is the UBA register
                    717:         * mapping (the first part of) the transfer.
                    718:         * O is offset within a memory page of the first byte transferred.
                    719:         */
                    720:        npf = btop((up->upwc * sizeof(short)) + bp->b_bcount) - 1;
                    721:        reg = btop(up_ubinfo&0x3ffff) + npf;
                    722:        o = (int)bp->b_un.b_addr & PGOFSET;
                    723:        printf("%D ", bp->b_blkno+npf);
                    724:        prdev("ECC", bp->b_dev);
                    725:        mask = up->upec2;
                    726:        if (mask == 0) {
                    727:                up->upof = FMT22;               /* == RTC ???? */
                    728:                DELAY(idelay);
                    729:                return (0);
                    730:        }
                    731:        /*
                    732:         * Flush the buffered data path, and compute the
                    733:         * byte and bit position of the error.  The variable i
                    734:         * is the byte offset in the transfer, the variable byte
                    735:         * is the offset from a page boundary in main memory.
                    736:         */
                    737:        ubp->uba_dpr[(up_ubinfo>>28)&0x0f] |= BNE;
                    738:        i = up->upec1 - 1;              /* -1 makes 0 origin */
                    739:        bit = i&07;
                    740:        i = (i&~07)>>3;
                    741:        byte = i + o;
                    742:        /*
                    743:         * Correct while possible bits remain of mask.  Since mask
                    744:         * contains 11 bits, we continue while the bit offset is > -11.
                    745:         * Also watch out for end of this block and the end of the whole
                    746:         * transfer.
                    747:         */
                    748:        while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) {
                    749:                addr = ptob(ubp->uba_map[reg+btop(byte)].pg_pfnum)+
                    750:                    (byte & PGOFSET);
                    751:                putmemc(addr, getmemc(addr)^(mask<<bit));
                    752:                byte++;
                    753:                i++;
                    754:                bit -= 8;
                    755:        }
                    756:        uptab.b_active++;       /* Either complete or continuing... */
                    757:        if (up->upwc == 0)
                    758:                return (0);
                    759:        /*
                    760:         * Have to continue the transfer... clear the drive,
                    761:         * and compute the position where the transfer is to continue.
                    762:         * We have completed npf+1 sectors of the transfer already;
                    763:         * restart at offset o of next sector (i.e. in UBA register reg+1).
                    764:         */
                    765:        up->upcs1 = TRE|IE|DCLR|GO;
                    766:        DELAY(idelay);
                    767:        bn = dkblock(bp);
                    768:        cn = bp->b_cylin;
                    769:        sn = bn%(NSECT*NTRAC) + npf + 1;
                    770:        tn = sn/NSECT;
                    771:        sn %= NSECT;
                    772:        cn += tn/NTRAC;
                    773:        tn %= NTRAC;
                    774:        up->updc = cn;
                    775:        up->upda = (tn << 8) | sn;
                    776:        ubaddr = (int)ptob(reg+1) + o;
                    777:        up->upba = ubaddr;
                    778:        cmd = (ubaddr >> 8) & 0x300;
                    779:        cmd |= IE|GO|RCOM;
                    780:        up->upcs1 = cmd;
                    781:        return (1);
                    782: }
                    783: 
                    784: /*
                    785:  * Reset driver after UBA init.
                    786:  * Cancel software state of all pending transfers
                    787:  * and restart all units and the controller.
                    788:  */
                    789: upreset()
                    790: {
                    791:        int unit;
                    792: 
                    793:        printf(" up");
                    794:        uptab.b_active = 0;
                    795:        uptab.b_actf = uptab.b_actl = 0;
                    796:        if (up_ubinfo) {
                    797:                printf("<%d>", (up_ubinfo>>28)&0xf);
                    798:                ubafree(up_ubinfo), up_ubinfo = 0;
                    799:        }
                    800:        UPADDR->upcs2 = CLR;            /* clear controller */
                    801:        DELAY(idelay);
                    802:        for (unit = 0; unit < NUP; unit++) {
                    803:                uputab[unit].b_active = 0;
                    804:                (void) upustart(unit);
                    805:        }
                    806:        (void) upstart();
                    807: }
                    808: 
                    809: /*
                    810:  * Wake up every second and if an interrupt is pending
                    811:  * but nothing has happened increment a counter.
                    812:  * If nothing happens for 20 seconds, reset the controller
                    813:  * and begin anew.
                    814:  */
                    815: upwatch()
                    816: {
                    817:        int i;
                    818: 
                    819:        timeout((caddr_t)upwatch, 0, HZ);
                    820:        if (uptab.b_active == 0) {
                    821:                for (i = 0; i < NUP; i++)
                    822:                        if (uputab[i].b_active)
                    823:                                goto active;
                    824:                up_wticks = 0;          /* idling */
                    825:                return;
                    826:        }
                    827: active:
                    828:        up_wticks++;
                    829:        if (up_wticks >= 20) {
                    830:                up_wticks = 0;
                    831:                printf("LOST INTERRUPT RESET");
                    832:                upreset();
                    833:                printf("\n");
                    834:        }
                    835: }

unix.superglobalmegacorp.com

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