Annotation of 42BSD/sys/stand/hp.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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