Annotation of 43BSDReno/sys/hpdev/cd.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1988 University of Utah.
                      3:  * Copyright (c) 1990 The Regents of the University of California.
                      4:  * All rights reserved.
                      5:  *
                      6:  * This code is derived from software contributed to Berkeley by
                      7:  * the Systems Programming Group of the University of Utah Computer
                      8:  * Science Department.
                      9:  *
                     10:  * Redistribution is only permitted until one year after the first shipment
                     11:  * of 4.4BSD by the Regents.  Otherwise, redistribution and use in source and
                     12:  * binary forms are permitted provided that: (1) source distributions retain
                     13:  * this entire copyright notice and comment, and (2) distributions including
                     14:  * binaries display the following acknowledgement:  This product includes
                     15:  * software developed by the University of California, Berkeley and its
                     16:  * contributors'' in the documentation or other materials provided with the
                     17:  * distribution and in all advertising materials mentioning features or use
                     18:  * of this software.  Neither the name of the University nor the names of
                     19:  * its contributors may be used to endorse or promote products derived from
                     20:  * this software without specific prior written permission.
                     21:  * THIS SOFTWARE IS PROVIDED AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
                     22:  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
                     23:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     24:  *
                     25:  * from: Utah $Hdr: cd.c 1.4 89/09/17$
                     26:  *
                     27:  *     @(#)cd.c        7.1 (Berkeley) 5/8/90
                     28:  */
                     29: 
                     30: /*
                     31:  * "Concatenated" disk driver.
                     32:  */
                     33: #include "cd.h"
                     34: #if NCD > 0
                     35: 
                     36: #include "param.h"
                     37: #include "systm.h"
                     38: #include "errno.h"
                     39: #include "dkstat.h"
                     40: #include "buf.h"
                     41: #include "malloc.h"
                     42: #include "conf.h"
                     43: 
                     44: #include "cdvar.h"
                     45: 
                     46: #ifdef DEBUG
                     47: int cddebug = 0x00;
                     48: #define CDB_FOLLOW     0x01
                     49: #define CDB_INIT       0x02
                     50: #define CDB_IO         0x04
                     51: #endif
                     52: 
                     53: struct buf cdbuf[NCD];
                     54: struct buf *cdbuffer();
                     55: int    cdiodone();
                     56: 
                     57: #define        cdunit(x)       ((minor(x) >> 3) & 0x7) /* for consistency */
                     58: 
                     59: #define        getcbuf()       \
                     60:        ((struct buf *)malloc(sizeof(struct buf), M_DEVBUF, M_WAITOK))
                     61: #define putcbuf(bp)    \
                     62:        free((caddr_t)(bp), M_DEVBUF)
                     63: 
                     64: struct cd_softc {
                     65:        int              sc_flags;              /* flags */
                     66:        size_t           sc_size;               /* size of cd */
                     67:        int              sc_ileave;             /* interleave */
                     68:        int              sc_ncdisks;            /* number of components */
                     69:        struct cdcinfo   sc_cinfo[NCDISKS];     /* component info */
                     70:        struct cdiinfo   *sc_itable;            /* interleave table */
                     71:        int              sc_usecnt;             /* number of requests active */
                     72:        struct buf       *sc_bp;                /* "current" request */
                     73:        int              sc_dk;                 /* disk index */
                     74: } cd_softc[NCD];
                     75: 
                     76: /* sc_flags */
                     77: #define        CDF_ALIVE       0x01
                     78: #define CDF_INITED     0x02
                     79: 
                     80: cdinit(cd)
                     81:        struct cddevice *cd;
                     82: {
                     83:        register struct cd_softc *cs = &cd_softc[cd->cd_unit];
                     84:        register struct cdcinfo *ci;
                     85:        register size_t size;
                     86:        register int ix;
                     87:        size_t minsize;
                     88:        dev_t dev;
                     89: 
                     90: #ifdef DEBUG
                     91:        if (cddebug & (CDB_FOLLOW|CDB_INIT))
                     92:                printf("cdinit: unit %d\n", cd->cd_unit);
                     93: #endif
                     94:        cs->sc_dk = cd->cd_dk;
                     95:        cs->sc_size = 0;
                     96:        cs->sc_ileave = cd->cd_interleave;
                     97:        cs->sc_ncdisks = 0;
                     98:        /*
                     99:         * Verify that each component piece exists and record
                    100:         * relevant information about it.
                    101:         */
                    102:        minsize = 0;
                    103:        for (ix = 0; ix < NCDISKS; ix++) {
                    104:                if ((dev = cd->cd_dev[ix]) == NODEV)
                    105:                        break;
                    106:                ci = &cs->sc_cinfo[ix];
                    107:                ci->ci_dev = dev;
                    108:                /*
                    109:                 * Calculate size (truncated to interleave boundary
                    110:                 * if necessary.
                    111:                 */
                    112:                if (bdevsw[major(dev)].d_psize) {
                    113:                        size = (*bdevsw[major(dev)].d_psize)(dev);
                    114:                        if (size <= 0)
                    115:                                size = 0;
                    116:                } else
                    117:                        size = 0;
                    118:                if (cs->sc_ileave > 1)
                    119:                        size -= size % cs->sc_ileave;
                    120:                if (size == 0)
                    121:                        return(0);
                    122:                if (minsize == 0 || size < minsize)
                    123:                        minsize = size;
                    124:                ci->ci_size = size;
                    125:                cs->sc_size += size;
                    126:                cs->sc_ncdisks++;
                    127:        }
                    128:        /*
                    129:         * If uniform interleave is desired set all sizes to that of
                    130:         * the smallest component.
                    131:         */
                    132:        if (cd->cd_flags & CDF_UNIFORM) {
                    133:                for (ci = cs->sc_cinfo;
                    134:                     ci < &cs->sc_cinfo[cs->sc_ncdisks]; ci++)
                    135:                        ci->ci_size = minsize;
                    136:                cs->sc_size = cs->sc_ncdisks * minsize;
                    137:        }
                    138:        /*
                    139:         * Construct the interleave table
                    140:         */
                    141:        if (!cdinterleave(cs))
                    142:                return(0);
                    143:        if (cd->cd_dk >= 0)
                    144:                dk_wpms[cd->cd_dk] = 32 * (60 * DEV_BSIZE / 2); /* XXX */
                    145:        printf("cd%d: %d components (%d blocks) concatenated",
                    146:               cd->cd_unit, cs->sc_ncdisks, cs->sc_size);
                    147:        if (cs->sc_ileave)
                    148:                printf(", %d block interleave\n", cs->sc_ileave);
                    149:        else
                    150:                printf(" serially\n");
                    151:        cs->sc_flags = CDF_ALIVE | CDF_INITED;
                    152:        return(1);
                    153: }
                    154: 
                    155: cdinterleave(cs)
                    156:        register struct cd_softc *cs;
                    157: {
                    158:        register struct cdcinfo *ci, *smallci;
                    159:        register struct cdiinfo *ii;
                    160:        register daddr_t bn, lbn;
                    161:        register int ix;
                    162:        u_long size;
                    163: 
                    164: #ifdef DEBUG
                    165:        if (cddebug & CDB_INIT)
                    166:                printf("cdinterleave(%x): ileave %d\n", cs, cs->sc_ileave);
                    167: #endif
                    168:        /*
                    169:         * Allocate an interleave table.
                    170:         * Chances are this is too big, but we don't care.
                    171:         */
                    172:        size = (cs->sc_ncdisks + 1) * sizeof(struct cdiinfo);
                    173:        cs->sc_itable = (struct cdiinfo *)malloc(size, M_DEVBUF, M_WAITOK);
                    174:        bzero((caddr_t)cs->sc_itable, size);
                    175:        /*
                    176:         * Trivial case: no interleave (actually interleave of disk size).
                    177:         * Each table entry represent a single component in its entirety.
                    178:         */
                    179:        if (cs->sc_ileave == 0) {
                    180:                bn = 0;
                    181:                ii = cs->sc_itable;
                    182:                for (ix = 0; ix < cs->sc_ncdisks; ix++) {
                    183:                        ii->ii_ndisk = 1;
                    184:                        ii->ii_startblk = bn;
                    185:                        ii->ii_startoff = 0;
                    186:                        ii->ii_index[0] = ix;
                    187:                        bn += cs->sc_cinfo[ix].ci_size;
                    188:                        ii++;
                    189:                }
                    190:                ii->ii_ndisk = 0;
                    191: #ifdef DEBUG
                    192:                if (cddebug & CDB_INIT)
                    193:                        printiinfo(cs->sc_itable);
                    194: #endif
                    195:                return(1);
                    196:        }
                    197:        /*
                    198:         * The following isn't fast or pretty; it doesn't have to be.
                    199:         */
                    200:        size = 0;
                    201:        bn = lbn = 0;
                    202:        for (ii = cs->sc_itable; ; ii++) {
                    203:                /*
                    204:                 * Locate the smallest of the remaining components
                    205:                 */
                    206:                smallci = NULL;
                    207:                for (ci = cs->sc_cinfo;
                    208:                     ci < &cs->sc_cinfo[cs->sc_ncdisks]; ci++)
                    209:                        if (ci->ci_size > size &&
                    210:                            (smallci == NULL ||
                    211:                             ci->ci_size < smallci->ci_size))
                    212:                                smallci = ci;
                    213:                /*
                    214:                 * Nobody left, all done
                    215:                 */
                    216:                if (smallci == NULL) {
                    217:                        ii->ii_ndisk = 0;
                    218:                        break;
                    219:                }
                    220:                /*
                    221:                 * Record starting logical block and component offset
                    222:                 */
                    223:                ii->ii_startblk = bn / cs->sc_ileave;
                    224:                ii->ii_startoff = lbn;
                    225:                /*
                    226:                 * Determine how many disks take part in this interleave
                    227:                 * and record their indices.
                    228:                 */
                    229:                ix = 0;
                    230:                for (ci = cs->sc_cinfo;
                    231:                     ci < &cs->sc_cinfo[cs->sc_ncdisks]; ci++)
                    232:                        if (ci->ci_size >= smallci->ci_size)
                    233:                                ii->ii_index[ix++] = ci - cs->sc_cinfo;
                    234:                ii->ii_ndisk = ix;
                    235:                bn += ix * (smallci->ci_size - size);
                    236:                lbn = smallci->ci_size / cs->sc_ileave;
                    237:                size = smallci->ci_size;
                    238:        }
                    239: #ifdef DEBUG
                    240:        if (cddebug & CDB_INIT)
                    241:                printiinfo(cs->sc_itable);
                    242: #endif
                    243:        return(1);
                    244: }
                    245: 
                    246: #ifdef DEBUG
                    247: printiinfo(ii)
                    248:        struct cdiinfo *ii;
                    249: {
                    250:        register int ix, i;
                    251: 
                    252:        for (ix = 0; ii->ii_ndisk; ix++, ii++) {
                    253:                printf(" itab[%d]: #dk %d sblk %d soff %d",
                    254:                       ix, ii->ii_ndisk, ii->ii_startblk, ii->ii_startoff);
                    255:                for (i = 0; i < ii->ii_ndisk; i++)
                    256:                        printf(" %d", ii->ii_index[i]);
                    257:                printf("\n");
                    258:        }
                    259: }
                    260: #endif
                    261: 
                    262: cdopen(dev, flags)
                    263:        dev_t dev;
                    264: {
                    265:        int unit = cdunit(dev);
                    266:        register struct cd_softc *cs = &cd_softc[unit];
                    267: 
                    268: #ifdef DEBUG
                    269:        if (cddebug & CDB_FOLLOW)
                    270:                printf("cdopen(%x, %x)\n", dev, flags);
                    271: #endif
                    272:        if (unit >= NCD || (cs->sc_flags & CDF_ALIVE) == 0)
                    273:                return(ENXIO);
                    274:        return(0);
                    275: }
                    276: 
                    277: cdstrategy(bp)
                    278:        register struct buf *bp;
                    279: {
                    280:        register int unit = cdunit(bp->b_dev);
                    281:        register struct cd_softc *cs = &cd_softc[unit];
                    282:        register int bn, sz;
                    283:        int s;
                    284: 
                    285: #ifdef DEBUG
                    286:        if (cddebug & CDB_FOLLOW)
                    287:                printf("cdstrategy(%x): unit %d\n", bp, unit);
                    288: #endif
                    289:        if ((cs->sc_flags & CDF_INITED) == 0) {
                    290:                bp->b_error = ENXIO;
                    291:                goto bad;
                    292:        }
                    293:        bn = bp->b_blkno;
                    294:        sz = (bp->b_bcount + (DEV_BSIZE - 1)) >> DEV_BSHIFT;
                    295:        bp->b_resid = bp->b_bcount;
                    296:        if (bn < 0 || bn + sz > cs->sc_size) {
                    297:                if (bn == cs->sc_size)
                    298:                        goto done;
                    299:                bp->b_error = EINVAL;
                    300:                goto bad;
                    301:        }
                    302:        /*
                    303:         * "Start" the unit.
                    304:         * XXX: the use of sc_bp is just to retain the "traditional"
                    305:         * interface to the start routine.
                    306:         */
                    307:        s = splbio();
                    308:        cs->sc_bp = bp;
                    309:        cdstart(unit);
                    310:        splx(s);
                    311:        return;
                    312: bad:
                    313:        bp->b_flags |= B_ERROR;
                    314: done:
                    315:        iodone(bp);
                    316: }
                    317: 
                    318: cdstart(unit)
                    319:        int unit;
                    320: {
                    321:        register struct cd_softc *cs = &cd_softc[unit];
                    322:        register struct buf *bp = cs->sc_bp;
                    323:        register long bcount, rcount;
                    324:        struct buf *cbp;
                    325:        caddr_t addr;
                    326:        daddr_t bn;
                    327: 
                    328: #ifdef DEBUG
                    329:        if (cddebug & CDB_FOLLOW)
                    330:                printf("cdstart(%d)\n", unit);
                    331: #endif
                    332:        /*
                    333:         * Instumentation (not real meaningful)
                    334:         */
                    335:        cs->sc_usecnt++;
                    336:        if (cs->sc_dk >= 0) {
                    337:                dk_busy |= 1 << cs->sc_dk;
                    338:                dk_xfer[cs->sc_dk]++;
                    339:                dk_wds[cs->sc_dk] += bp->b_bcount >> 6;
                    340:        }
                    341:        /*
                    342:         * Allocate component buffers and fire off the requests
                    343:         */
                    344:        bn = bp->b_blkno;
                    345:        addr = bp->b_un.b_addr;
                    346:        for (bcount = bp->b_bcount; bcount > 0; bcount -= rcount) {
                    347:                cbp = cdbuffer(cs, bp, bn, addr, bcount);
                    348:                rcount = cbp->b_bcount;
                    349:                (*bdevsw[major(cbp->b_dev)].d_strategy)(cbp);
                    350:                bn += btodb(rcount);
                    351:                addr += rcount;
                    352:        }
                    353: }
                    354: 
                    355: /*
                    356:  * Build a component buffer header.
                    357:  */
                    358: struct buf *
                    359: cdbuffer(cs, bp, bn, addr, bcount)
                    360:        register struct cd_softc *cs;
                    361:        struct buf *bp;
                    362:        daddr_t bn;
                    363:        caddr_t addr;
                    364:        long bcount;
                    365: {
                    366:        register struct cdcinfo *ci;
                    367:        register struct buf *cbp;
                    368:        register daddr_t cbn, cboff;
                    369: 
                    370: #ifdef DEBUG
                    371:        if (cddebug & CDB_IO)
                    372:                printf("cdbuffer(%x, %x, %d, %x, %d)\n",
                    373:                       cs, bp, bn, addr, bcount);
                    374: #endif
                    375:        /*
                    376:         * Determine which component bn falls in.
                    377:         */
                    378:        cbn = bn;
                    379:        cboff = 0;
                    380:        /*
                    381:         * Serially concatenated
                    382:         */
                    383:        if (cs->sc_ileave == 0) {
                    384:                register daddr_t sblk;
                    385: 
                    386:                sblk = 0;
                    387:                for (ci = cs->sc_cinfo; cbn >= sblk + ci->ci_size; ci++)
                    388:                        sblk += ci->ci_size;
                    389:                cbn -= sblk;
                    390:        }
                    391:        /*
                    392:         * Interleaved
                    393:         */
                    394:        else {
                    395:                register struct cdiinfo *ii;
                    396:                int cdisk, off;
                    397: 
                    398:                cboff = cbn % cs->sc_ileave;
                    399:                cbn /= cs->sc_ileave;
                    400:                for (ii = cs->sc_itable; ii->ii_ndisk; ii++)
                    401:                        if (ii->ii_startblk > cbn)
                    402:                                break;
                    403:                ii--;
                    404:                off = cbn - ii->ii_startblk;
                    405:                if (ii->ii_ndisk == 1) {
                    406:                        cdisk = ii->ii_index[0];
                    407:                        cbn = ii->ii_startoff + off;
                    408:                } else {
                    409:                        cdisk = ii->ii_index[off % ii->ii_ndisk];
                    410:                        cbn = ii->ii_startoff + off / ii->ii_ndisk;
                    411:                }
                    412:                cbn *= cs->sc_ileave;
                    413:                ci = &cs->sc_cinfo[cdisk];
                    414:        }
                    415:        /*
                    416:         * Fill in the component buf structure.
                    417:         */
                    418:        cbp = getcbuf();
                    419:        cbp->b_flags = bp->b_flags | B_CALL;
                    420:        cbp->b_iodone = cdiodone;
                    421:        cbp->b_proc = bp->b_proc;
                    422:        cbp->b_dev = ci->ci_dev;
                    423:        cbp->b_blkno = cbn + cboff;
                    424:        cbp->b_un.b_addr = addr;
                    425:        if (cs->sc_ileave == 0)
                    426:                cbp->b_bcount = dbtob(ci->ci_size - cbn);
                    427:        else
                    428:                cbp->b_bcount = dbtob(cs->sc_ileave - cboff);
                    429:        if (cbp->b_bcount > bcount)
                    430:                cbp->b_bcount = bcount;
                    431:        /*
                    432:         * XXX: context for cdiodone
                    433:         */
                    434:        cbp->b_vp = (struct vnode *)bp;
                    435:        cbp->b_pfcent = ((cs - cd_softc) << 16) | (ci - cs->sc_cinfo);
                    436: #ifdef DEBUG
                    437:        if (cddebug & CDB_IO)
                    438:                printf(" dev %x(u%d): cbp %x bn %d addr %x bcnt %d\n",
                    439:                       ci->ci_dev, ci-cs->sc_cinfo, cbp, cbp->b_blkno,
                    440:                       cbp->b_un.b_addr, cbp->b_bcount);
                    441: #endif
                    442:        return(cbp);
                    443: }
                    444: 
                    445: cdintr(unit)
                    446:        int unit;
                    447: {
                    448:        register struct cd_softc *cs = &cd_softc[unit];
                    449:        register struct buf *bp = cs->sc_bp;
                    450: 
                    451: #ifdef DEBUG
                    452:        if (cddebug & CDB_FOLLOW)
                    453:                printf("cdintr(%d)\n", unit);
                    454: #endif
                    455:        /*
                    456:         * Request is done for better or worse, wakeup the top half.
                    457:         */
                    458:        if (--cs->sc_usecnt == 0 && cs->sc_dk >= 0)
                    459:                dk_busy &= ~(1 << cs->sc_dk);
                    460:        if (bp->b_flags & B_ERROR)
                    461:                bp->b_resid = bp->b_bcount;
                    462:        iodone(bp);
                    463: }
                    464: 
                    465: /*
                    466:  * Called by iodone at interrupt time.
                    467:  * Mark the component as done and if all components are done,
                    468:  * take a cd interrupt.
                    469:  */
                    470: cdiodone(cbp)
                    471:        register struct buf *cbp;
                    472: {
                    473:        register struct buf *bp = (struct buf *)cbp->b_vp;      /* XXX */
                    474:        register int unit = (cbp->b_pfcent >> 16) & 0xFFFF;     /* XXX */
                    475:        int count, s;
                    476: 
                    477:        s = splbio();
                    478: #ifdef DEBUG
                    479:        if (cddebug & CDB_FOLLOW)
                    480:                printf("cdiodone(%x)\n", cbp);
                    481:        if (cddebug & CDB_IO) {
                    482:                printf("cdiodone: bp %x bcount %d resid %d\n",
                    483:                       bp, bp->b_bcount, bp->b_resid);
                    484:                printf(" dev %x(u%d), cbp %x bn %d addr %x bcnt %d\n",
                    485:                       cbp->b_dev, cbp->b_pfcent & 0xFFFF, cbp,
                    486:                       cbp->b_blkno, cbp->b_un.b_addr, cbp->b_bcount);
                    487:        }
                    488: #endif
                    489: 
                    490:        if (cbp->b_flags & B_ERROR) {
                    491:                bp->b_flags |= B_ERROR;
                    492:                bp->b_error = geterror(cbp);
                    493: #ifdef DEBUG
                    494:                printf("cd%d: error %d on component %d\n",
                    495:                       unit, bp->b_error, cbp->b_pfcent & 0xFFFF);
                    496: #endif
                    497:        }
                    498:        count = cbp->b_bcount;
                    499:        putcbuf(cbp);
                    500: 
                    501:        /*
                    502:         * If all done, "interrupt".
                    503:         * Again, sc_bp is only used to preserve the traditional interface.
                    504:         */
                    505:        bp->b_resid -= count;
                    506:        if (bp->b_resid < 0)
                    507:                panic("cdiodone: count");
                    508:        if (bp->b_resid == 0) {
                    509:                cd_softc[unit].sc_bp = bp;
                    510:                cdintr(unit);
                    511:        }
                    512:        splx(s);
                    513: }
                    514: 
                    515: cdread(dev, uio)
                    516:        dev_t dev;
                    517:        struct uio *uio;
                    518: {
                    519:        register int unit = cdunit(dev);
                    520: 
                    521: #ifdef DEBUG
                    522:        if (cddebug & CDB_FOLLOW)
                    523:                printf("cdread(%x, %x)\n", dev, uio);
                    524: #endif
                    525:        return(physio(cdstrategy, &cdbuf[unit], dev, B_READ, minphys, uio));
                    526: }
                    527: 
                    528: cdwrite(dev, uio)
                    529:        dev_t dev;
                    530:        struct uio *uio;
                    531: {
                    532:        register int unit = cdunit(dev);
                    533: 
                    534: #ifdef DEBUG
                    535:        if (cddebug & CDB_FOLLOW)
                    536:                printf("cdwrite(%x, %x)\n", dev, uio);
                    537: #endif
                    538:        return(physio(cdstrategy, &cdbuf[unit], dev, B_WRITE, minphys, uio));
                    539: }
                    540: 
                    541: cdioctl(dev, cmd, data, flag)
                    542:        dev_t dev;
                    543:        int cmd;
                    544:        caddr_t data;
                    545:        int flag;
                    546: {
                    547:        return(EINVAL);
                    548: }
                    549: 
                    550: cdsize(dev)
                    551:        dev_t dev;
                    552: {
                    553:        int unit = cdunit(dev);
                    554:        register struct cd_softc *cs = &cd_softc[unit];
                    555: 
                    556:        if (unit >= NCD || (cs->sc_flags & CDF_INITED) == 0)
                    557:                return(-1);
                    558:        return(cs->sc_size);
                    559: }
                    560: 
                    561: cddump(dev)
                    562: {
                    563:        return(ENXIO);
                    564: }
                    565: #endif

unix.superglobalmegacorp.com

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