Annotation of 43BSD/sys/stand/hp.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1982, 1986 Regents of the University of California.
        !             3:  * All rights reserved.  The Berkeley software License Agreement
        !             4:  * specifies the terms and conditions for redistribution.
        !             5:  *
        !             6:  *     @(#)hp.c        7.1 (Berkeley) 6/5/86
        !             7:  */
        !             8: 
        !             9: /*
        !            10:  * RP??/RM?? disk driver
        !            11:  * with ECC handling and bad block forwarding.
        !            12:  * Also supports header io operations and
        !            13:  * commands to write check header and data.
        !            14:  */
        !            15: #include "../h/param.h"
        !            16: #include "../h/inode.h"
        !            17: #include "../h/fs.h"
        !            18: #include "../h/dkbad.h"
        !            19: 
        !            20: #include "../vax/pte.h"
        !            21: #include "../vaxmba/hpreg.h"
        !            22: #include "../vaxmba/mbareg.h"
        !            23: 
        !            24: #include "saio.h"
        !            25: #include "savax.h"
        !            26: 
        !            27: #define        RETRIES         27
        !            28: 
        !            29: #define        MASKREG(reg)    ((reg)&0xffff)
        !            30: 
        !            31: #define        MAXBADDESC      126
        !            32: #define        SECTSIZ         512     /* sector size in bytes */
        !            33: #define        HDRSIZ          4       /* number of bytes in sector header */
        !            34: 
        !            35: extern struct st hpst[];
        !            36: extern short hptypes[];
        !            37: 
        !            38: #define        RP06 (hptypes[sc->type] == MBDT_RP06 || hptypes[sc->type] == MBDT_RP05 \
        !            39:        || hptypes[sc->type] == MBDT_RP04)
        !            40: #define        ML11 (hptypes[sc->type] == MBDT_ML11A)
        !            41: #define        RM80 (hptypes[sc->type] == MBDT_RM80)
        !            42: 
        !            43: u_char hp_offset[16] = {
        !            44:     HPOF_P400, HPOF_M400, HPOF_P400, HPOF_M400,
        !            45:     HPOF_P800, HPOF_M800, HPOF_P800, HPOF_M800,
        !            46:     HPOF_P1200, HPOF_M1200, HPOF_P1200, HPOF_M1200,
        !            47:     0, 0, 0, 0,
        !            48: };
        !            49: 
        !            50: struct dkbad hpbad[MAXNMBA*8];
        !            51: 
        !            52: struct hp_softc {
        !            53:        char    type;
        !            54:        char    gottype;
        !            55:        char    ssect;          /* 1 when on track w/skip sector */
        !            56:        char    debug;
        !            57: #      define  HPF_BSEDEBUG    01      /* debugging bad sector forwarding */
        !            58: #      define  HPF_ECCDEBUG    02      /* debugging ecc correction */
        !            59:        int     ecclim;
        !            60:        int     retries;
        !            61: } hp_softc[MAXNMBA * 8];
        !            62: 
        !            63: int    sectsiz;
        !            64: 
        !            65: /*
        !            66:  * When awaiting command completion, don't
        !            67:  * hang on to the status register since
        !            68:  * this ties up some controllers.
        !            69:  */
        !            70: #define        HPWAIT(addr) \
        !            71:        while ((((addr)->hpds)&HPDS_DRY)==0) DELAY(500);
        !            72: 
        !            73: hpopen(io)
        !            74:        register struct iob *io;
        !            75: {
        !            76:        register unit = io->i_unit;
        !            77:        struct hpdevice *hpaddr = (struct hpdevice *)mbadrv(unit);
        !            78:        register struct st *st;
        !            79:        register struct hp_softc *sc = &hp_softc[unit];
        !            80: 
        !            81:        mbainit(UNITTOMBA(unit));
        !            82:        if (sc->gottype == 0) {
        !            83:                register i, type = hpaddr->hpdt & MBDT_TYPE;
        !            84:                struct iob tio;
        !            85: 
        !            86:                for (i = 0; hptypes[i]; i++)
        !            87:                        if (hptypes[i] == type)
        !            88:                                goto found;
        !            89:                _stop("unknown drive type");
        !            90: found:
        !            91:                sc->retries = RETRIES;
        !            92:                sc->ecclim = 11;
        !            93:                sc->debug = 0;
        !            94:                hpaddr->hpcs1 = HP_DCLR|HP_GO;          /* init drive */
        !            95:                hpaddr->hpcs1 = HP_PRESET|HP_GO;
        !            96:                if (!ML11)
        !            97:                        hpaddr->hpof = HPOF_FMT22;
        !            98:                sc->type = hpmaptype(hpaddr, i, UNITTODRIVE(unit));
        !            99:                /*
        !           100:                 * Read in the bad sector table.
        !           101:                 */
        !           102:                st = &hpst[sc->type];
        !           103:                tio = *io;
        !           104:                tio.i_bn = st->nspc * st->ncyl - st->nsect;
        !           105:                tio.i_ma = (char *)&hpbad[unit];
        !           106:                tio.i_cc = sizeof (struct dkbad);
        !           107:                tio.i_flgs |= F_RDDATA;
        !           108:                for (i = 0; i < 5; i++) {
        !           109:                        if (hpstrategy(&tio, READ) == sizeof (struct dkbad))
        !           110:                                break;
        !           111:                        tio.i_bn += 2;
        !           112:                }
        !           113:                if (i == 5) {
        !           114:                        printf("Unable to read bad sector table\n");
        !           115:                        for (i = 0; i < MAXBADDESC; i++) {
        !           116:                                hpbad[unit].bt_bad[i].bt_cyl = -1;
        !           117:                                hpbad[unit].bt_bad[i].bt_trksec = -1;
        !           118:                        }
        !           119:                }
        !           120:                sc->gottype = 1;
        !           121:        }
        !           122:        st = &hpst[sc->type];
        !           123:        if (io->i_boff < 0 || io->i_boff > 7 ||
        !           124:            st->off[io->i_boff]== -1)
        !           125:                _stop("hp bad minor");
        !           126:        io->i_boff = st->off[io->i_boff] * st->nspc;
        !           127: }
        !           128: 
        !           129: hpstrategy(io, func)
        !           130:        register struct iob *io;
        !           131: {
        !           132:        register unit = io->i_unit;
        !           133:        struct mba_regs *mba = mbamba(unit);
        !           134:        daddr_t bn, startblock;
        !           135:        struct hpdevice *hpaddr = (struct hpdevice *)mbadrv(unit);
        !           136:        register struct hp_softc *sc = &hp_softc[unit];
        !           137:        struct st *st = &hpst[sc->type];
        !           138:        int cn, tn, sn, bytecnt, bytesleft, rv; 
        !           139:        char *membase;
        !           140:        int er1, er2, hprecal;
        !           141: 
        !           142:        sectsiz = SECTSIZ;
        !           143:        if ((io->i_flgs & (F_HDR|F_HCHECK)) != 0)
        !           144:                sectsiz += HDRSIZ;
        !           145:        if ((hpaddr->hpds & HPDS_VV) == 0) {
        !           146:                hpaddr->hpcs1 = HP_DCLR|HP_GO;
        !           147:                hpaddr->hpcs1 = HP_PRESET|HP_GO;
        !           148:                if (!ML11)
        !           149:                        hpaddr->hpof = HPOF_FMT22;
        !           150:        }
        !           151:        io->i_errcnt = 0;
        !           152:        sc->ssect = 0;
        !           153:        rv = bytecnt = io->i_cc;
        !           154:        membase = io->i_ma;
        !           155:        startblock = io->i_bn;
        !           156:        hprecal = 0;
        !           157: 
        !           158: restart:
        !           159:        bn = io->i_bn;
        !           160:        cn = bn/st->nspc;
        !           161:        sn = bn%st->nspc;
        !           162:        tn = sn/st->nsect;
        !           163:        sn = sn%st->nsect + sc->ssect;
        !           164: 
        !           165:        HPWAIT(hpaddr);
        !           166:        mba->mba_sr = -1;
        !           167:        if (ML11)
        !           168:                hpaddr->hpda = bn;
        !           169:        else {
        !           170:                hpaddr->hpdc = cn;
        !           171:                hpaddr->hpda = (tn << 8) + sn;
        !           172:        }
        !           173:        if (mbastart(io, func) != 0) {          /* start transfer */
        !           174:                rv = -1;
        !           175:                goto done;
        !           176:        }
        !           177:        HPWAIT(hpaddr);
        !           178:        /*
        !           179:         * Successful data transfer, return.
        !           180:         */
        !           181:        if ((hpaddr->hpds&HPDS_ERR) == 0 && (mba->mba_sr&MBSR_EBITS) == 0)
        !           182:                goto done;
        !           183: 
        !           184:        /*
        !           185:         * Error handling.  Calculate location of error.
        !           186:         */
        !           187:        bytesleft = MASKREG(mba->mba_bcr);
        !           188:        if (bytesleft) 
        !           189:                bytesleft |= 0xffff0000;        /* sxt */
        !           190:        bn = io->i_bn + (io->i_cc + bytesleft) / sectsiz;
        !           191:        er1 = MASKREG(hpaddr->hper1);
        !           192:        er2 = MASKREG(hpaddr->hper2);
        !           193:        if (er1 & (HPER1_DCK|HPER1_ECH))
        !           194:                bn--;   /* Error is in Prev block */
        !           195:        cn = bn/st->nspc;
        !           196:        sn = bn%st->nspc;
        !           197:        tn = sn/st->nsect;
        !           198:        sn = sn%st->nsect;
        !           199:        if (sc->debug & (HPF_ECCDEBUG|HPF_BSEDEBUG)) {
        !           200:                printf("hp error: sn%d (cyl,trk,sec)=(%d,%d,%d) ds=%b\n",
        !           201:                        bn, cn, tn, sn, MASKREG(hpaddr->hpds), HPDS_BITS);
        !           202:                printf("er1=%b er2=%b\n", er1, HPER1_BITS, er2, HPER2_BITS);
        !           203:                printf("bytes left: %d, of 0x%x, da 0x%x\n",-bytesleft,
        !           204:                        hpaddr->hpof, hpaddr->hpda);
        !           205:        }
        !           206:        if (er1 & HPER1_HCRC) {
        !           207:                er1 &= ~(HPER1_HCE|HPER1_FER);
        !           208:                er2 &= ~HPER2_BSE;
        !           209:                if ((io->i_flgs&F_NBSF) == 0 && hpecc(io, BSE) == 0)
        !           210:                        goto success;
        !           211:        }
        !           212:        /*
        !           213:         * Give up early if drive write locked.
        !           214:         */
        !           215:        if (er1&HPER1_WLE) {
        !           216:                printf("hp%d: write locked\n", unit);
        !           217:                rv = -1;
        !           218:                goto done;
        !           219:        }
        !           220:        /*
        !           221:         * Skip sector handling.
        !           222:         */
        !           223:        if (RM80 && (er2 & HPER2_SSE)) {
        !           224:                (void) hpecc(io, SSE);
        !           225:                sc->ssect = 1;
        !           226:                goto restart;
        !           227:        }
        !           228:        /*
        !           229:         * Attempt to forward bad sectors on anything but an ML11.
        !           230:         * Interpret format error bit as a bad block on RP06's.
        !           231:         */
        !           232:        if (((er2 & HPER2_BSE) && !ML11) ||
        !           233:            (MASKREG(er1) == HPER1_FER && RP06)) {
        !           234:                if (io->i_flgs & F_NBSF) {
        !           235:                        io->i_error = EBSE;     
        !           236:                        goto hard;
        !           237:                }
        !           238:                if (hpecc(io, BSE) == 0)
        !           239:                        goto success;
        !           240:                io->i_error = EBSE;
        !           241:                goto hard;
        !           242:        }
        !           243:        /*
        !           244:         * ECC correction?
        !           245:         */
        !           246:        if ((er1 & (HPER1_DCK|HPER1_ECH)) == HPER1_DCK) {
        !           247:                if (hpecc(io, ECC) == 0)
        !           248:                        goto success;
        !           249:                io->i_error = EECC;
        !           250:                goto hard;
        !           251:        } 
        !           252: 
        !           253:        /*
        !           254:         * If a hard error, or maximum retry count
        !           255:         * exceeded, clear controller state and
        !           256:         * pass back error to caller.
        !           257:         */
        !           258:        if (++io->i_errcnt > sc->retries || (er1 & HPER1_HARD) ||
        !           259:            (!ML11 && (er2 & HPER2_HARD)) || (ML11 && (io->i_errcnt >= 16))) {
        !           260:                io->i_error = EHER;
        !           261:                if (mba->mba_sr & (MBSR_WCKUP|MBSR_WCKLWR))
        !           262:                        io->i_error = EWCK;
        !           263: hard:
        !           264:                io->i_errblk = bn + sc->ssect;
        !           265:                if (sc->debug & (HPF_BSEDEBUG|HPF_ECCDEBUG))
        !           266:                    printf(" dc=%d, da=0x%x",MASKREG(hpaddr->hpdc),
        !           267:                          MASKREG(hpaddr->hpda));
        !           268:                else {
        !           269:                    printf("hp error: sn%d (cyl,trk,sec)=(%d,%d,%d) ds=%b \n",
        !           270:                           bn, cn, tn, sn, MASKREG(hpaddr->hpds), HPDS_BITS);
        !           271:                    printf("er1=%b er2=%b", er1, HPER1_BITS, er2, HPER2_BITS);
        !           272:                }
        !           273:                hpaddr->hpcs1 = HP_DCLR|HP_GO;
        !           274:                printf("\n");
        !           275:                rv = -1;
        !           276:                goto done;
        !           277: 
        !           278:        }
        !           279:        /* fall thru to retry */
        !           280:        hpaddr->hpcs1 = HP_DCLR|HP_GO;
        !           281:        HPWAIT(hpaddr);
        !           282: 
        !           283:        /* 
        !           284:         * Every fourth retry recalibrate.
        !           285:         */
        !           286:        if (((io->i_errcnt & 07) == 4) ) {
        !           287:                hpaddr->hpcs1 = HP_RECAL|HP_GO;
        !           288:                HPWAIT(hpaddr);
        !           289:                hpaddr->hpdc = cn;
        !           290:                hpaddr->hpcs1 = HP_SEEK|HP_GO;
        !           291:                HPWAIT(hpaddr);
        !           292:        }
        !           293: 
        !           294:        if (io->i_errcnt >= 16 && (io->i_flgs & F_READ)) {
        !           295:                hpaddr->hpof = hp_offset[io->i_errcnt & 017]|HPOF_FMT22;
        !           296:                hpaddr->hpcs1 = HP_OFFSET|HP_GO;
        !           297:                HPWAIT(hpaddr);
        !           298:        }
        !           299:        if (sc->debug & (HPF_ECCDEBUG|HPF_BSEDEBUG))
        !           300:                printf("restart: bn=%d, cc=%d, ma=0x%x hprecal=%d\n",
        !           301:                  io->i_bn, io->i_cc, io->i_ma, hprecal);
        !           302:        goto restart;
        !           303: 
        !           304: success:
        !           305:        /*
        !           306:         * On successful error recovery, bump
        !           307:         * block number to advance to next portion
        !           308:         * of i/o transfer.
        !           309:         */
        !           310:        bn++;
        !           311:        if ((bn-startblock) * sectsiz < bytecnt) {
        !           312:                io->i_bn = bn;
        !           313:                io->i_ma = membase + (io->i_bn - startblock)*sectsiz;
        !           314:                io->i_cc = bytecnt - (io->i_bn - startblock)*sectsiz;
        !           315:                if (sc->debug & (HPF_ECCDEBUG|HPF_BSEDEBUG))
        !           316:                        printf("restart: bn=%d, cc=%d, ma=0x%x hprecal=%d\n",
        !           317:                          io->i_bn, io->i_cc, io->i_ma, hprecal);
        !           318:                goto restart;
        !           319:        }
        !           320: done:
        !           321:        if (io->i_errcnt >= 16) {
        !           322:                hpaddr->hpcs1 = HP_RTC|HP_GO;
        !           323:                while (hpaddr->hpds & HPDS_PIP)
        !           324:                        ;
        !           325:        }
        !           326:        io->i_bn = startblock;          /*reset i_bn to original */
        !           327:        io->i_cc = bytecnt;             /*reset i_cc to total count xfered*/
        !           328:        io->i_ma = membase;             /*reset i_ma to original */
        !           329:        return (rv);
        !           330: }
        !           331: 
        !           332: hpecc(io, flag)
        !           333:        register struct iob *io;
        !           334:        int flag;
        !           335: {
        !           336:        register unit = io->i_unit;
        !           337:        register struct mba_regs *mbp = mbamba(unit);
        !           338:        register struct hpdevice *rp = (struct hpdevice *)mbadrv(unit);
        !           339:        register struct hp_softc *sc = &hp_softc[unit];
        !           340:        register struct st *st = &hpst[sc->type];
        !           341:        int npf, bn, cn, tn, sn, bcr;
        !           342: 
        !           343:        bcr = MASKREG(mbp->mba_bcr);
        !           344:        if (bcr)
        !           345:                bcr |= 0xffff0000;              /* sxt */
        !           346:        npf = (bcr + io->i_cc) / sectsiz;       /* # sectors read */
        !           347:        if (flag == ECC)
        !           348:                npf--;          /* Error is in prev block --ghg */
        !           349:        bn = io->i_bn + npf + sc->ssect;        /* physical block #*/
        !           350:        if (sc->debug & HPF_ECCDEBUG)
        !           351:                printf("bcr=%d npf=%d ssect=%d sectsiz=%d i_cc=%d\n",
        !           352:                        bcr, npf, sc->ssect, sectsiz, io->i_cc);
        !           353:        /*
        !           354:         * ECC correction logic.
        !           355:         */
        !           356:        if (flag == ECC) {
        !           357:                register int i;
        !           358:                caddr_t addr;
        !           359:                int bit, o, mask;
        !           360: 
        !           361:                printf("hp%d: soft ecc sn%d\n", unit, bn);
        !           362:                mask = MASKREG(rp->hpec2);
        !           363:                for (i = mask, bit = 0; i; i >>= 1)
        !           364:                        if (i & 1)
        !           365:                                bit++;
        !           366:                if (bit > sc->ecclim) {
        !           367:                        printf("%d-bit error\n", bit);
        !           368:                        return (1);
        !           369:                }
        !           370:                i = MASKREG(rp->hpec1) - 1;     /* -1 makes 0 origin */
        !           371:                bit = i&07;
        !           372:                o = (i & ~07) >> 3;
        !           373:                rp->hpcs1 = HP_DCLR | HP_GO;
        !           374:                while (o <sectsiz && npf*sectsiz + o < io->i_cc && bit > -11) {
        !           375:                        addr = io->i_ma + (npf*sectsiz) + o;
        !           376:                        /*
        !           377:                         * No data transfer occurs with a write check,
        !           378:                         * so don't correct the resident copy of data.
        !           379:                         */
        !           380:                        if ((io->i_flgs & (F_CHECK|F_HCHECK)) == 0) {
        !           381:                                if (sc->debug & HPF_ECCDEBUG)
        !           382:                                        printf("addr=%x old=%x ", addr,
        !           383:                                                (*addr & 0xff));
        !           384:                                *addr ^= (mask << bit);
        !           385:                                if (sc->debug & HPF_ECCDEBUG)
        !           386:                                        printf("new=%x\n",(*addr & 0xff));
        !           387:                        }
        !           388:                        o++, bit -= 8;
        !           389:                }
        !           390:                return (0);
        !           391:        }
        !           392: 
        !           393:        /*
        !           394:         * Skip sector error.
        !           395:         * Set skip-sector-inhibit and
        !           396:         * read next sector
        !           397:         */
        !           398:        if (flag == SSE) {
        !           399:                rp->hpcs1 = HP_DCLR | HP_GO;
        !           400:                HPWAIT(rp);
        !           401:                rp->hpof |= HPOF_SSEI;
        !           402:                return (0);     
        !           403:        }
        !           404: 
        !           405:        /*
        !           406:         * Bad block forwarding.
        !           407:         */
        !           408:         if (flag == BSE) {
        !           409:                int bbn;
        !           410: 
        !           411:                rp->hpcs1 = HP_DCLR | HP_GO;
        !           412:                if (sc->debug & HPF_BSEDEBUG)
        !           413:                        printf("hpecc: BSE @ bn %d\n", bn);
        !           414:                cn = bn/st->nspc;
        !           415:                sn = bn%st->nspc;
        !           416:                tn = sn/st->nsect;
        !           417:                sn = sn%st->nsect;
        !           418:                bcr += sectsiz;
        !           419:                if ((bbn = isbad(&hpbad[unit], cn, tn, sn)) < 0)
        !           420:                        return (1);
        !           421:                bbn = st->ncyl*st->nspc - st->nsect - 1 - bbn;
        !           422:                cn = bbn/st->nspc;
        !           423:                sn = bbn%st->nspc;
        !           424:                tn = sn/st->nsect;
        !           425:                sn = sn%st->nsect;
        !           426:                io->i_cc = sectsiz;
        !           427:                io->i_ma += npf*sectsiz;
        !           428:                if (sc->debug & HPF_BSEDEBUG)
        !           429:                        printf("revector to cn %d tn %d sn %d\n", cn, tn, sn);
        !           430:                rp->hpof &= ~HPOF_SSEI;
        !           431:                mbp->mba_sr = -1;
        !           432:                rp->hpdc = cn;
        !           433:                rp->hpda = (tn<<8) + sn;
        !           434:                mbastart(io,io->i_flgs);
        !           435:                io->i_errcnt = 0;
        !           436:                HPWAIT(rp);
        !           437:                return (rp->hpds&HPDS_ERR);
        !           438:        }
        !           439:        printf("hpecc: flag=%d\n", flag);
        !           440:        return (1);
        !           441: }
        !           442: 
        !           443: /*ARGSUSED*/
        !           444: hpioctl(io, cmd, arg)
        !           445:        struct iob *io;
        !           446:        int cmd;
        !           447:        caddr_t arg;
        !           448: {
        !           449:        register unit = io->i_unit;
        !           450:        register struct hp_softc *sc = &hp_softc[unit];
        !           451:        struct st *st = &hpst[sc->type];
        !           452:        struct mba_drv *drv = mbadrv(unit);
        !           453: 
        !           454:        switch(cmd) {
        !           455: 
        !           456:        case SAIODEBUG:
        !           457:                sc->debug = (int)arg;
        !           458:                break;
        !           459: 
        !           460:        case SAIODEVDATA:
        !           461:                if (drv->mbd_dt&MBDT_TAP)
        !           462:                        return (ECMD);
        !           463:                *(struct st *)arg = *st;
        !           464:                break;
        !           465: 
        !           466:        case SAIOGBADINFO:
        !           467:                if (drv->mbd_dt&MBDT_TAP)
        !           468:                        return (ECMD);
        !           469:                *(struct dkbad *)arg = hpbad[unit];
        !           470:                break;
        !           471: 
        !           472:        case SAIOECCLIM:
        !           473:                sc->ecclim = (int)arg;
        !           474:                break;
        !           475: 
        !           476:        case SAIORETRIES:
        !           477:                sc->retries = (int)arg;
        !           478:                break;
        !           479: 
        !           480:        case SAIOSSI:                   /* skip-sector-inhibit */
        !           481:                if (drv->mbd_dt&MBDT_TAP)
        !           482:                        return (ECMD);
        !           483:                if ((io->i_flgs&F_SSI) == 0) {
        !           484:                        /* make sure this is done once only */
        !           485:                        io->i_flgs |= F_SSI;
        !           486:                        st->nsect++;
        !           487:                        st->nspc += st->ntrak;
        !           488:                }
        !           489:                break;
        !           490: 
        !           491:        case SAIONOSSI:                 /* remove skip-sector-inhibit */
        !           492:                if (io->i_flgs & F_SSI) {
        !           493:                        io->i_flgs &= ~F_SSI;
        !           494:                        drv->mbd_of &= ~HPOF_SSEI;
        !           495:                        st->nsect--;
        !           496:                        st->nspc -= st->ntrak;
        !           497:                }
        !           498:                break;
        !           499: 
        !           500:        case SAIOSSDEV:                 /* drive have skip sector? */
        !           501:                return (RM80 ? 0 : ECMD);
        !           502: 
        !           503:        default:
        !           504:                return (ECMD);
        !           505:        }
        !           506:        return (0);
        !           507: }

unix.superglobalmegacorp.com

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