Annotation of 40BSD/sys/dev/hp.c, revision 1.1.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.