Annotation of 40BSD/sys/dev/hp.c, revision 1.1

1.1     ! root        1: /*     hp.c    4.1     11/9/80 */
        !             2: 
        !             3: #include "../conf/hp.h"
        !             4: #if NHP > 0
        !             5: /*
        !             6:  * RP06/RM03/RM05 disk driver
        !             7:  */
        !             8: 
        !             9: #include "../h/param.h"
        !            10: #include "../h/systm.h"
        !            11: #include "../h/dk.h"
        !            12: #include "../h/buf.h"
        !            13: #include "../h/conf.h"
        !            14: #include "../h/dir.h"
        !            15: #include "../h/user.h"
        !            16: #include "../h/map.h"
        !            17: #include "../h/pte.h"
        !            18: #include "../h/mba.h"
        !            19: #include "../h/mtpr.h"
        !            20: #include "../h/vm.h"
        !            21: 
        !            22: struct device
        !            23: {
        !            24:        int     hpcs1;          /* control and Status register 1 */
        !            25:        int     hpds;           /* Drive Status */
        !            26:        int     hper1;          /* Error register 1 */
        !            27:        int     hpmr;           /* Maintenance */ 
        !            28:        int     hpas;           /* Attention Summary */
        !            29:        int     hpda;           /* Desired address register */
        !            30:        int     hpdt;           /* Drive type */
        !            31:        int     hpla;           /* Look ahead */
        !            32:        int     hpsn;           /* serial number */
        !            33:        int     hpof;           /* Offset register */
        !            34:        int     hpdc;           /* Desired Cylinder address register */
        !            35:        int     hpcc;           /* Current Cylinder */
        !            36:        int     hper2;          /* Error register 2 */
        !            37:        int     hper3;          /* Error register 3 */
        !            38:        int     hpec1;          /* Burst error bit position */
        !            39:        int     hpec2;          /* Burst error bit pattern */
        !            40: };
        !            41: 
        !            42: #define        RP      022
        !            43: #define        RM      024
        !            44: #define        RM5     027
        !            45: #define        NSECT   22
        !            46: #define        NTRAC   19
        !            47: #define        NRMSECT 32
        !            48: #define        NRMTRAC 5
        !            49: 
        !            50: #define        _hpSDIST        2
        !            51: #define        _hpRDIST        3
        !            52: 
        !            53: int    hpSDIST = _hpSDIST;
        !            54: int    hpRDIST = _hpRDIST;
        !            55: int    hpseek;
        !            56: 
        !            57: struct size
        !            58: {
        !            59:        daddr_t nblocks;
        !            60:        int     cyloff;
        !            61: } hp_sizes[8] =
        !            62: {
        !            63:        15884,  0,              /* A=cyl 0 thru 37 */
        !            64:        33440,  38,             /* B=cyl 38 thru 117 */
        !            65:        340670, 0,              /* C=cyl 0 thru 814 */
        !            66:        0,      0,
        !            67:        0,      0,
        !            68:        0,      0,
        !            69:        291346, 118,            /* G=cyl 118 thru 814 */
        !            70:        0,      0,
        !            71: }, rm_sizes[8] = {
        !            72:        15884,  0,              /* A=cyl 0 thru 99 */
        !            73:        33440,  100,            /* B=cyl 100 thru 309 */
        !            74:        131680, 0,              /* C=cyl 0 thru 822 */
        !            75:        0,      0,
        !            76:        0,      0,
        !            77:        0,      0,
        !            78:        82080,  310,            /* G=cyl 310 thru 822 */
        !            79:        0,      0,
        !            80: }, rm5_sizes[8] = {
        !            81:        15884,  0,              /* A=cyl 0 thru 26 */
        !            82:        33440,  27,             /* B=cyl 27 thru 81 */
        !            83:        500992, 0,              /* C=cyl 0 thru 823 */
        !            84:        15884,  562,            /* D=cyl 562 thru 588 */
        !            85:        55936,  589,            /* E=cyl 589 thru 680 */
        !            86:        86944,  681,            /* F=cyl 681 thru 823 */
        !            87:        159296, 562,            /* G=cyl 562 thru 823 */
        !            88:        291346, 82,             /* H=cyl 82 thru 561 */
        !            89: };
        !            90: 
        !            91: #define        P400    020
        !            92: #define        M400    0220
        !            93: #define        P800    040
        !            94: #define        M800    0240
        !            95: #define        P1200   060
        !            96: #define        M1200   0260
        !            97: int    hp_offset[16] =
        !            98: {
        !            99:        P400, M400, P400, M400,
        !           100:        P800, M800, P800, M800,
        !           101:        P1200, M1200, P1200, M1200,
        !           102:        0, 0, 0, 0,
        !           103: };
        !           104: 
        !           105: struct buf     hptab;
        !           106: struct buf     rhpbuf;
        !           107: struct buf     hputab[NHP];
        !           108: char   hp_type[NHP];   /* drive type */
        !           109: 
        !           110: #define        GO      01
        !           111: #define        PRESET  020
        !           112: #define        RTC     016
        !           113: #define        OFFSET  014
        !           114: #define        SEEK    04
        !           115: #define        SEARCH  030
        !           116: #define        RECAL   06
        !           117: #define        DCLR    010
        !           118: #define        WCOM    060
        !           119: #define        RCOM    070
        !           120: 
        !           121: #define        IE      0100
        !           122: #define        PIP     020000
        !           123: #define        DRY     0200
        !           124: #define        ERR     040000
        !           125: #define        TRE     040000
        !           126: #define        DCK     0100000
        !           127: #define        WLE     04000
        !           128: #define        ECH     0100
        !           129: #define        VV      0100
        !           130: #define        DPR     0400
        !           131: #define        MOL     010000
        !           132: #define        FMT22   010000
        !           133: 
        !           134: #define        b_cylin b_resid
        !           135:  
        !           136: #ifdef INTRLVE
        !           137: daddr_t dkblock();
        !           138: #endif
        !           139:  
        !           140: hpstrategy(bp)
        !           141: register struct buf *bp;
        !           142: {
        !           143:        register struct buf *dp;
        !           144:        register unit, xunit, nspc;
        !           145:        long sz, bn;
        !           146:        struct size *sizes;
        !           147: 
        !           148:        if ((mbaact&(1<<HPMBANUM)) == 0)
        !           149:                mbainit(HPMBANUM);
        !           150:        xunit = minor(bp->b_dev) & 077;
        !           151:        sz = bp->b_bcount;
        !           152:        sz = (sz+511) >> 9;
        !           153:        unit = dkunit(bp);
        !           154:        if (hp_type[unit] == 0) {
        !           155:                struct device *hpaddr;
        !           156:                double mspw;
        !           157: 
        !           158:                /* determine device type */
        !           159:                hpaddr = mbadev(HPMBA, unit);
        !           160: 
        !           161:                /* record transfer rate (these are guesstimates secs/word) */
        !           162:                switch (hp_type[unit] = hpaddr->hpdt) {
        !           163:                case RM:        mspw = .0000019728; break;
        !           164:                case RM5:       mspw = .0000020345; break;
        !           165:                case RP:        mspw = .0000029592; break;
        !           166:                }
        !           167:                if (DK_N + unit <= DK_NMAX)
        !           168:                        dk_mspw[DK_N+unit] = mspw;
        !           169:        }
        !           170:        switch (hp_type[unit]) {
        !           171: 
        !           172:        case RM:
        !           173:                sizes = rm_sizes;
        !           174:                nspc = NRMSECT*NRMTRAC;
        !           175:                break;
        !           176:        case RM5:
        !           177:                sizes = rm5_sizes;
        !           178:                nspc = NRMSECT*NTRAC;
        !           179:                break;
        !           180:        case RP:
        !           181:                sizes = hp_sizes;
        !           182:                nspc = NSECT*NTRAC;
        !           183:                break;
        !           184:        default:
        !           185:                printf("hp: unknown device type 0%o\n", hp_type[unit]);
        !           186:                u.u_error = ENXIO;
        !           187:                unit = NHP+1;   /* force error */
        !           188:        }
        !           189:        if (unit >= NHP ||
        !           190:            bp->b_blkno < 0 ||
        !           191:            (bn = dkblock(bp))+sz > sizes[xunit&07].nblocks) {
        !           192:                bp->b_flags |= B_ERROR;
        !           193:                iodone(bp);
        !           194:                return;
        !           195:        }
        !           196:        bp->b_cylin = bn/nspc + sizes[xunit&07].cyloff;
        !           197:        dp = &hputab[unit];
        !           198:        (void) spl5();
        !           199:        disksort(dp, bp);
        !           200:        if (dp->b_active == 0) {
        !           201:                hpustart(unit);
        !           202:                if(hptab.b_active == 0)
        !           203:                        hpstart();
        !           204:        }
        !           205:        (void) spl0();
        !           206: }
        !           207: 
        !           208: hpustart(unit)
        !           209: register unit;
        !           210: {
        !           211:        register struct buf *bp, *dp;
        !           212:        register struct device *hpaddr;
        !           213:        daddr_t bn;
        !           214:        int sn, cn, csn;
        !           215: 
        !           216:        ((struct mba_regs *)HPMBA)->mba_cr |= MBAIE;
        !           217:        hpaddr = mbadev(HPMBA, 0);
        !           218:        hpaddr->hpas = 1<<unit;
        !           219: 
        !           220:        if(unit >= NHP)
        !           221:                return;
        !           222:        if (unit+DK_N <= DK_NMAX)
        !           223:                dk_busy &= ~(1<<(unit+DK_N));
        !           224:        dp = &hputab[unit];
        !           225:        if((bp=dp->b_actf) == NULL)
        !           226:                return;
        !           227:        hpaddr = mbadev(HPMBA, unit);
        !           228:        if((hpaddr->hpds & VV) == 0) {
        !           229:                hpaddr->hpcs1 = PRESET|GO;
        !           230:                hpaddr->hpof = FMT22;
        !           231:        }
        !           232:        if(dp->b_active)
        !           233:                goto done;
        !           234:        dp->b_active++;
        !           235:        if ((hpaddr->hpds & (DPR|MOL)) != (DPR|MOL))
        !           236:                goto done;
        !           237: 
        !           238:        bn = dkblock(bp);
        !           239:        cn = bp->b_cylin;
        !           240:        switch (hp_type[unit]) {
        !           241: 
        !           242:        case RM:
        !           243:                sn = bn%(NRMSECT*NRMTRAC);
        !           244:                sn = (sn+NRMSECT-hpSDIST)%NRMSECT;
        !           245:                break;
        !           246:        case RM5:
        !           247:                sn = bn%(NRMSECT*NTRAC);
        !           248:                sn = (sn+NRMSECT-hpSDIST)%NRMSECT;
        !           249:                break;
        !           250:        case RP:
        !           251:                sn = bn%(NSECT*NTRAC);
        !           252:                sn = (sn+NSECT-hpSDIST)%NSECT;
        !           253:                break;
        !           254:        default:
        !           255:                panic("hpustart");
        !           256:        }
        !           257: 
        !           258:        if(cn - (hpaddr->hpdc & 0xffff))
        !           259:                goto search;
        !           260:        else if (hpseek)
        !           261:                goto done;
        !           262:        csn = ((hpaddr->hpla & 0xffff)>>6) - sn + 1;
        !           263:        if(csn < 0)
        !           264:                csn += NSECT;
        !           265:        if(csn > NSECT-hpRDIST)
        !           266:                goto done;
        !           267: 
        !           268: search:
        !           269:        hpaddr->hpdc = cn;
        !           270:        if (hpseek)
        !           271:                hpaddr->hpcs1 = SEEK|GO;
        !           272:        else {
        !           273:                hpaddr->hpda = sn;
        !           274:                hpaddr->hpcs1 = SEARCH|GO;
        !           275:        }
        !           276:        unit += DK_N;
        !           277:        if (unit <= DK_NMAX) {
        !           278:                dk_busy |= 1<<unit;
        !           279:                dk_seek[unit]++;
        !           280:        }
        !           281:        return;
        !           282: 
        !           283: done:
        !           284:        dp->b_forw = NULL;
        !           285:        if(hptab.b_actf == NULL)
        !           286:                hptab.b_actf = dp;
        !           287:        else
        !           288:                hptab.b_actl->b_forw = dp;
        !           289:        hptab.b_actl = dp;
        !           290: }
        !           291: 
        !           292: hpstart()
        !           293: {
        !           294:        register struct buf *bp, *dp;
        !           295:        register unit;
        !           296:        register struct device *hpaddr;
        !           297:        daddr_t bn;
        !           298:        int dn, sn, tn, cn, nspc, ns;
        !           299: 
        !           300: loop:
        !           301:        if ((dp = hptab.b_actf) == NULL)
        !           302:                return;
        !           303:        if ((bp = dp->b_actf) == NULL) {
        !           304:                hptab.b_actf = dp->b_forw;
        !           305:                goto loop;
        !           306:        }
        !           307:        hptab.b_active++;
        !           308:        unit = minor(bp->b_dev) & 077;
        !           309:        dn = dkunit(bp);
        !           310:        bn = dkblock(bp);
        !           311:        switch (hp_type[dn]) {
        !           312:        case RM:
        !           313:                nspc = NRMSECT*NRMTRAC;
        !           314:                ns = NRMSECT;
        !           315:                cn = rm_sizes[unit&07].cyloff;
        !           316:                break;
        !           317:        case RM5:
        !           318:                nspc = NRMSECT*NTRAC;
        !           319:                ns = NRMSECT;
        !           320:                cn = rm5_sizes[unit&07].cyloff;
        !           321:                break;
        !           322:        case RP:
        !           323:                nspc = NSECT*NTRAC;
        !           324:                ns = NSECT;
        !           325:                cn = hp_sizes[unit&07].cyloff;
        !           326:                break;
        !           327:        default:
        !           328:                panic("hpstart");
        !           329:        }
        !           330:        cn += bn/nspc;
        !           331:        sn = bn%nspc;
        !           332:        tn = sn/ns;
        !           333:        sn = sn%ns;
        !           334: 
        !           335:        hpaddr = mbadev(HPMBA, dn);
        !           336:        if ((hpaddr->hpds & (DPR|MOL)) != (DPR|MOL)) {
        !           337:                hptab.b_active = 0;
        !           338:                hptab.b_errcnt = 0;
        !           339:                dp->b_actf = bp->av_forw;
        !           340:                bp->b_flags |= B_ERROR;
        !           341:                iodone(bp);
        !           342:                goto loop;
        !           343:        }
        !           344:        if(hptab.b_errcnt >= 16 && (bp->b_flags&B_WRITE) == 0) {
        !           345:                hpaddr->hpof = hp_offset[hptab.b_errcnt & 017] | FMT22;
        !           346:                HPMBA->mba_cr &= ~MBAIE;
        !           347:                hpaddr->hpcs1 = OFFSET|GO;
        !           348:                while(hpaddr->hpds & PIP)
        !           349:                        ;
        !           350:                HPMBA->mba_cr |= MBAIE;
        !           351:        }
        !           352:        hpaddr->hpdc = cn;
        !           353:        hpaddr->hpda = (tn << 8) + sn;
        !           354:        mbastart(bp, (int *)hpaddr);
        !           355: 
        !           356:        unit = dn+DK_N;
        !           357:        if (unit <= DK_NMAX) {
        !           358:                dk_busy |= 1<<unit;
        !           359:                dk_xfer[unit]++;
        !           360:                dk_wds[unit] += bp->b_bcount>>6;
        !           361:        }
        !           362: }
        !           363: 
        !           364: hpintr(mbastat, as)
        !           365: {
        !           366:        register struct buf *bp, *dp;
        !           367:        register unit;
        !           368:        register struct device *hpaddr;
        !           369: 
        !           370:        if(hptab.b_active) {
        !           371:                dp = hptab.b_actf;
        !           372:                bp = dp->b_actf;
        !           373:                unit = dkunit(bp);
        !           374:                if (DK_N+unit <= DK_NMAX)
        !           375:                        dk_busy &= ~(1<<(DK_N+unit));
        !           376:                hpaddr = mbadev(HPMBA, unit);
        !           377:                if (hpaddr->hpds & ERR || mbastat & MBAEBITS) {
        !           378:                        while((hpaddr->hpds & DRY) == 0)
        !           379:                                ;
        !           380:                        if(++hptab.b_errcnt > 28 || hpaddr->hper1&WLE)
        !           381:                                bp->b_flags |= B_ERROR;
        !           382:                        else
        !           383:                                hptab.b_active = 0;
        !           384:                        if(hptab.b_errcnt > 27)
        !           385:                                deverror(bp, mbastat, hpaddr->hper1);
        !           386:                        if ((hpaddr->hper1&0xffff) == DCK) {
        !           387:                                if (hpecc(hpaddr, bp))
        !           388:                                        return;
        !           389:                        }
        !           390:                        hpaddr->hpcs1 = DCLR|GO;
        !           391:                        if((hptab.b_errcnt&07) == 4) {
        !           392:                                HPMBA->mba_cr &= ~MBAIE;
        !           393:                                hpaddr->hpcs1 = RECAL|GO;
        !           394:                                while(hpaddr->hpds & PIP)
        !           395:                                        ;
        !           396:                                HPMBA->mba_cr |= MBAIE;
        !           397:                        }
        !           398:                }
        !           399:                if(hptab.b_active) {
        !           400:                        if(hptab.b_errcnt) {
        !           401:                                HPMBA->mba_cr &= ~MBAIE;
        !           402:                                hpaddr->hpcs1 = RTC|GO;
        !           403:                                while(hpaddr->hpds & PIP)
        !           404:                                        ;
        !           405:                                HPMBA->mba_cr |= MBAIE;
        !           406:                        }
        !           407:                        hptab.b_active = 0;
        !           408:                        hptab.b_errcnt = 0;
        !           409:                        hptab.b_actf = dp->b_forw;
        !           410:                        dp->b_active = 0;
        !           411:                        dp->b_errcnt = 0;
        !           412:                        dp->b_actf = bp->av_forw;
        !           413:                        bp->b_resid = -HPMBA->mba_bcr & 0xffff;
        !           414:                        iodone(bp);
        !           415:                        if(dp->b_actf)
        !           416:                                hpustart(unit);
        !           417:                }
        !           418:                as &= ~(1<<unit);
        !           419:        } else {
        !           420:                if(as == 0)
        !           421:                        HPMBA->mba_cr |= MBAIE;
        !           422:        }
        !           423:        for(unit=0; unit<NHP; unit++)
        !           424:                if(as & (1<<unit))
        !           425:                        hpustart(unit);
        !           426:        hpstart();
        !           427: }
        !           428: 
        !           429: hpread(dev)
        !           430: {
        !           431: 
        !           432:        physio(hpstrategy, &rhpbuf, dev, B_READ, minphys);
        !           433: }
        !           434: 
        !           435: hpwrite(dev)
        !           436: {
        !           437: 
        !           438:        physio(hpstrategy, &rhpbuf, dev, B_WRITE, minphys);
        !           439: }
        !           440: 
        !           441: hpecc(rp, bp)
        !           442: register struct device *rp;
        !           443: register struct buf *bp;
        !           444: {
        !           445:        struct mba_regs *mbp = HPMBA;
        !           446:        register int i;
        !           447:        caddr_t addr;
        !           448:        int reg, bit, byte, npf, mask, o;
        !           449:        int dn, bn, cn, tn, sn, ns, nt;
        !           450:        extern char buffers[NBUF][BSIZE];
        !           451:        struct pte mpte;
        !           452:        int bcr;
        !           453: 
        !           454:        /*
        !           455:         * Npf is the number of sectors transferred before the sector
        !           456:         * containing the ECC error, and reg is the MBA register
        !           457:         * mapping (the first part of)the transfer.
        !           458:         * O is offset within a memory page of the first byte transferred.
        !           459:         */
        !           460:        bcr = mbp->mba_bcr & 0xffff;
        !           461:        if (bcr)
        !           462:                bcr |= 0xffff0000;              /* sxt */
        !           463:        npf = btop(bcr + bp->b_bcount) - 1;
        !           464:        reg = npf;
        !           465:        o = (int)bp->b_un.b_addr & PGOFSET;
        !           466:        printf("%D ", bp->b_blkno + npf);
        !           467:        prdev("ECC", bp->b_dev);
        !           468:        mask = rp->hpec2&0xffff;
        !           469:        if (mask == 0) {
        !           470:                rp->hpof = FMT22;
        !           471:                return (0);
        !           472:        }
        !           473: 
        !           474:        /*
        !           475:         * Compute the byte and bit position of the error.
        !           476:         * The variable i is the byte offset in the transfer,
        !           477:         * the variable byte is the offset from a page boundary
        !           478:         * in main memory.
        !           479:         */
        !           480:        i = (rp->hpec1&0xffff) - 1;             /* -1 makes 0 origin */
        !           481:        bit = i&07;
        !           482:        i = (i&~07)>>3;
        !           483:        byte = i + o;
        !           484:        /*
        !           485:         * Correct while possible bits remain of mask.  Since mask
        !           486:         * contains 11 bits, we continue while the bit offset is > -11.
        !           487:         * Also watch out for end of this block and the end of the whole
        !           488:         * transfer.
        !           489:         */
        !           490:        while (i < 512 && (int)ptob(npf)+i < bp->b_bcount && bit > -11) {
        !           491:                mpte = mbp->mba_map[reg+btop(byte)];
        !           492:                addr = ptob(mpte.pg_pfnum) + (byte & PGOFSET);
        !           493:                putmemc(addr, getmemc(addr)^(mask<<bit));
        !           494:                byte++;
        !           495:                i++;
        !           496:                bit -= 8;
        !           497:        }
        !           498:        hptab.b_active++;               /* Either complete or continuing */
        !           499:        if (bcr == 0)
        !           500:                return (0);
        !           501:        /*
        !           502:         * Have to continue the transfer... clear the drive,
        !           503:         * and compute the position where the transfer is to continue.
        !           504:         * We have completed npf+1 sectores of the transfer already;
        !           505:         * restart at offset o of next sector (i.e. in MBA register reg+1).
        !           506:         */
        !           507:        rp->hpcs1 = DCLR|GO;
        !           508:        dn = dkunit(bp);
        !           509:        bn = dkblock(bp);
        !           510:        switch (hp_type[dn]) {
        !           511: 
        !           512:        case RM:
        !           513:                ns = NRMSECT; nt = NRMTRAC; break;
        !           514:        case RM5:
        !           515:                ns = NRMSECT; nt = NTRAC; break;
        !           516:        case RP:
        !           517:                ns = NSECT; nt = NTRAC; break;
        !           518:        default:
        !           519:                panic("hpecc");
        !           520:        }
        !           521:        cn = bp->b_cylin;
        !           522:        sn = bn%(ns*nt) + npf + 1;
        !           523:        tn = sn/ns;
        !           524:        sn %= ns;
        !           525:        cn += tn/nt;
        !           526:        tn %= nt;
        !           527:        rp->hpdc = cn;
        !           528:        rp->hpda = (tn<<8) + sn;
        !           529:        mbp->mba_sr = -1;
        !           530:        mbp->mba_var = (int)ptob(reg+1) + o;
        !           531:        rp->hpcs1 = RCOM|GO;
        !           532:        return (1);
        !           533: }
        !           534: #endif

unix.superglobalmegacorp.com

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