[BACK]Return to ccd.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev

Annotation of src/sys/dev/ccd.c, Revision 1.4

1.4     ! mycroft     1: /*     $NetBSD: ccd.c,v 1.3 1994/07/02 06:03:47 hpeyerl Exp $      */
1.2       cgd         2:
1.1       hpeyerl     3: /*
                      4:  * Copyright (c) 1988 University of Utah.
1.3       hpeyerl     5:  * Copyright (c) 1990, 1993
                      6:  *     The Regents of the University of California.  All rights reserved.
1.1       hpeyerl     7:  *
                      8:  * This code is derived from software contributed to Berkeley by
                      9:  * the Systems Programming Group of the University of Utah Computer
                     10:  * Science Department.
                     11:  *
                     12:  * Redistribution and use in source and binary forms, with or without
                     13:  * modification, are permitted provided that the following conditions
                     14:  * are met:
                     15:  * 1. Redistributions of source code must retain the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer.
                     17:  * 2. Redistributions in binary form must reproduce the above copyright
                     18:  *    notice, this list of conditions and the following disclaimer in the
                     19:  *    documentation and/or other materials provided with the distribution.
                     20:  * 3. All advertising materials mentioning features or use of this software
                     21:  *    must display the following acknowledgement:
                     22:  *     This product includes software developed by the University of
                     23:  *     California, Berkeley and its contributors.
                     24:  * 4. Neither the name of the University nor the names of its contributors
                     25:  *    may be used to endorse or promote products derived from this software
                     26:  *    without specific prior written permission.
                     27:  *
                     28:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     29:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     30:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     31:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     32:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     33:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     34:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     35:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     36:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     37:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     38:  * SUCH DAMAGE.
                     39:  *
1.2       cgd        40:  * from: Utah $Hdr: cd.c 1.6 90/11/28$
                     41:  *
1.3       hpeyerl    42:  *     @(#)cd.c        8.2 (Berkeley) 11/16/93
1.1       hpeyerl    43:  */
                     44:
                     45: /*
                     46:  * "Concatenated" disk driver.
                     47:  */
                     48: #include "ccd.h"
                     49: #if NCCD > 0
                     50:
                     51: #include <sys/param.h>
                     52: #include <sys/systm.h>
1.3       hpeyerl    53: #include <sys/proc.h>
1.1       hpeyerl    54: #include <sys/errno.h>
                     55: #include <sys/dkstat.h>
                     56: #include <sys/buf.h>
                     57: #include <sys/malloc.h>
                     58: #include <sys/conf.h>
1.3       hpeyerl    59: #include <sys/stat.h>
                     60: #ifdef COMPAT_NOLABEL
                     61: #include <sys/ioctl.h>
                     62: #include <sys/disklabel.h>
                     63: #include <sys/fcntl.h>
                     64: #endif
1.1       hpeyerl    65:
                     66: #include <dev/ccdvar.h>
                     67:
                     68: #ifdef DEBUG
                     69: int ccddebug = 0x00;
1.3       hpeyerl    70: #define CCDB_FOLLOW    0x01
                     71: #define CCDB_INIT      0x02
                     72: #define CCDB_IO                0x04
1.1       hpeyerl    73: #endif
                     74:
                     75: struct buf *ccdbuffer();
                     76: char   *ccddevtostr();
1.3       hpeyerl    77: void   ccdiodone();
1.1       hpeyerl    78:
1.3       hpeyerl    79: #define        ccdunit(x)      ((minor(x) >> 3) & 0xf) /* for consistency */
1.1       hpeyerl    80:
                     81: #define        getcbuf()       \
                     82:        ((struct buf *)malloc(sizeof(struct buf), M_DEVBUF, M_WAITOK))
                     83: #define putcbuf(bp)    \
                     84:        free((caddr_t)(bp), M_DEVBUF)
                     85:
                     86: struct ccd_softc {
                     87:        int              sc_flags;              /* flags */
                     88:        size_t           sc_size;               /* size of ccd */
                     89:        int              sc_ileave;             /* interleave */
                     90:        int              sc_nccdisks;           /* number of components */
                     91:        struct ccdcinfo  sc_cinfo[NCCDISKS];    /* component info */
                     92:        struct ccdiinfo  *sc_itable;            /* interleave table */
                     93:        int              sc_usecnt;             /* number of requests active */
                     94:        int              sc_dk;                 /* disk index */
1.3       hpeyerl    95: };
1.1       hpeyerl    96:
                     97: /* sc_flags */
1.3       hpeyerl    98: #define        CCDF_ALIVE      0x01
                     99: #define CCDF_INITED    0x02
                    100:
                    101: struct ccd_softc *ccd_softc;
                    102: int numccd;
1.1       hpeyerl   103:
1.3       hpeyerl   104: /*
                    105:  * Since this is called after auto-configuration of devices,
                    106:  * we can handle the initialization here.
                    107:  *
                    108:  * XXX this will not work if you want to use a ccd as your primary
                    109:  * swap device since swapconf() has been called before now.
1.1       hpeyerl   110:  */
                    111: void
1.3       hpeyerl   112: ccdattach(num)
                    113:        int num;
                    114: {
                    115:        char *mem;
                    116:        register u_long size;
                    117:        register struct ccddevice *ccd;
                    118:        extern int dkn;
                    119:
                    120:        if (num <= 0)
                    121:                return;
                    122:        size = num * sizeof(struct ccd_softc);
                    123:        mem = malloc(size, M_DEVBUF, M_NOWAIT);
                    124:        if (mem == NULL) {
                    125:                printf("WARNING: no memory for concatonated disks\n");
                    126:                return;
                    127:        }
                    128:        bzero(mem, size);
                    129:        ccd_softc = (struct ccd_softc *)mem;
                    130:        numccd = num;
                    131:        for (ccd = ccddevice; ccd->ccd_unit >= 0; ccd++) {
                    132:                /*
                    133:                 * XXX
                    134:                 * Assign disk index first so that init routine
                    135:                 * can use it (saves having the driver drag around
                    136:                 * the ccddevice pointer just to set up the dk_*
                    137:                 * info in the open routine).
                    138:                 */
                    139:                if (dkn < DK_NDRIVE)
                    140:                        ccd->ccd_dk = dkn++;
                    141:                else
                    142:                        ccd->ccd_dk = -1;
                    143:                if (ccdinit(ccd))
                    144:                        printf("ccd%d configured\n", ccd->ccd_unit);
                    145:                else if (ccd->ccd_dk >= 0) {
                    146:                        ccd->ccd_dk = -1;
                    147:                        dkn--;
                    148:                }
                    149:        }
1.1       hpeyerl   150: }
                    151:
                    152: ccdinit(ccd)
                    153:        struct ccddevice *ccd;
                    154: {
                    155:        register struct ccd_softc *cs = &ccd_softc[ccd->ccd_unit];
                    156:        register struct ccdcinfo *ci;
                    157:        register size_t size;
                    158:        register int ix;
                    159:        size_t minsize;
                    160:        dev_t dev;
1.3       hpeyerl   161:        struct bdevsw *bsw;
                    162:        int error;
                    163:        struct proc *p = curproc; /* XXX */
1.1       hpeyerl   164:
                    165: #ifdef DEBUG
1.3       hpeyerl   166:        if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))
1.1       hpeyerl   167:                printf("ccdinit: unit %d\n", ccd->ccd_unit);
                    168: #endif
                    169:        cs->sc_dk = ccd->ccd_dk;
                    170:        cs->sc_size = 0;
                    171:        cs->sc_ileave = ccd->ccd_interleave;
                    172:        cs->sc_nccdisks = 0;
                    173:        /*
                    174:         * Verify that each component piece exists and record
                    175:         * relevant information about it.
                    176:         */
                    177:        minsize = 0;
                    178:        for (ix = 0; ix < NCCDISKS; ix++) {
                    179:                if ((dev = ccd->ccd_dev[ix]) == NODEV)
                    180:                        break;
                    181:                ci = &cs->sc_cinfo[ix];
                    182:                ci->ci_dev = dev;
1.3       hpeyerl   183:                bsw = &bdevsw[major(dev)];
                    184:                /*
                    185:                 * Open the partition
                    186:                 */
                    187:                if (bsw->d_open &&
                    188:                    (error = (*bsw->d_open)(dev, 0, S_IFBLK, p))) {
                    189:                        printf("ccd%d: component %s open failed, error = %d\n",
                    190:                               ccd->ccd_unit, ccddevtostr(dev), error);
                    191:                        return(0);
                    192:                }
1.1       hpeyerl   193:                /*
                    194:                 * Calculate size (truncated to interleave boundary
                    195:                 * if necessary.
                    196:                 */
1.3       hpeyerl   197:                if (bsw->d_psize) {
                    198:                        size = (size_t) (*bsw->d_psize)(dev);
1.1       hpeyerl   199:                        if ((int)size < 0)
                    200:                                size = 0;
                    201:                } else
                    202:                        size = 0;
                    203:                if (cs->sc_ileave > 1)
                    204:                        size -= size % cs->sc_ileave;
                    205:                if (size == 0) {
                    206:                        printf("ccd%d: not configured (component %s missing)\n",
1.3       hpeyerl   207:                               ccd->ccd_unit, ccddevtostr(dev));
1.1       hpeyerl   208:                        return(0);
                    209:                }
1.3       hpeyerl   210: #ifdef COMPAT_NOLABEL
                    211:                /*
                    212:                 * XXX if this is a 'c' partition then we need to mark the
                    213:                 * label area writeable since there cannot be a label.
                    214:                 */
                    215:                if ((minor(dev) & 7) == 2 && bsw->d_open) {
                    216:                        int i, flag;
                    217:
                    218:                        for (i = 0; i < nchrdev; i++)
1.4     ! mycroft   219:                                if (cdevsw[i].d_open == bsw->d_open)
1.3       hpeyerl   220:                                        break;
1.4     ! mycroft   221:                        if (i != nchrdev && cdevsw[i].d_ioctl) {
1.3       hpeyerl   222:                                flag = 1;
1.4     ! mycroft   223:                                (void)(*cdevsw[i].d_ioctl)(dev, DIOCWLABEL,
1.3       hpeyerl   224:                                        (caddr_t)&flag, FWRITE, p);
                    225:                        }
                    226:                }
                    227: #endif
1.1       hpeyerl   228:                if (minsize == 0 || size < minsize)
                    229:                        minsize = size;
                    230:                ci->ci_size = size;
                    231:                cs->sc_size += size;
                    232:                cs->sc_nccdisks++;
                    233:        }
                    234:        /*
                    235:         * If uniform interleave is desired set all sizes to that of
                    236:         * the smallest component.
                    237:         */
1.3       hpeyerl   238:        if (ccd->ccd_flags & CCDF_UNIFORM) {
1.1       hpeyerl   239:                for (ci = cs->sc_cinfo;
                    240:                     ci < &cs->sc_cinfo[cs->sc_nccdisks]; ci++)
                    241:                        ci->ci_size = minsize;
                    242:                cs->sc_size = cs->sc_nccdisks * minsize;
                    243:        }
                    244:        /*
                    245:         * Construct the interleave table
                    246:         */
                    247:        if (!ccdinterleave(cs))
                    248:                return(0);
                    249:        if (ccd->ccd_dk >= 0)
                    250:                dk_wpms[ccd->ccd_dk] = 32 * (60 * DEV_BSIZE / 2);       /* XXX */
                    251:        printf("ccd%d: %d components ", ccd->ccd_unit, cs->sc_nccdisks);
                    252:        for (ix = 0; ix < cs->sc_nccdisks; ix++)
                    253:                printf("%c%s%c",
                    254:                       ix == 0 ? '(' : ' ',
                    255:                       ccddevtostr(cs->sc_cinfo[ix].ci_dev),
                    256:                       ix == cs->sc_nccdisks - 1 ? ')' : ',');
                    257:        printf(", %d blocks ", cs->sc_size);
                    258:        if (cs->sc_ileave)
                    259:                printf("interleaved at %d blocks\n", cs->sc_ileave);
                    260:        else
                    261:                printf("concatenated\n");
1.3       hpeyerl   262:        cs->sc_flags = CCDF_ALIVE | CCDF_INITED;
1.1       hpeyerl   263:        return(1);
                    264: }
                    265:
                    266: /*
                    267:  * XXX not really ccd specific.
1.3       hpeyerl   268:  * Could be called something like bdevtostr in machine/conf.c.
1.1       hpeyerl   269:  */
                    270: char *
                    271: ccddevtostr(dev)
                    272:        dev_t dev;
                    273: {
                    274:        static char dbuf[5];
                    275:
                    276:        switch (major(dev)) {
1.3       hpeyerl   277: #ifdef hp300
1.1       hpeyerl   278:        case 2:
1.3       hpeyerl   279:                dbuf[0] = 'r'; dbuf[1] = 'd';
1.1       hpeyerl   280:                break;
                    281:        case 4:
1.3       hpeyerl   282:                dbuf[0] = 's'; dbuf[1] = 'd';
1.1       hpeyerl   283:                break;
                    284:        case 5:
1.3       hpeyerl   285:                dbuf[0] = 'c'; dbuf[1] = 'd';
                    286:                break;
                    287:        case 6:
                    288:                dbuf[0] = 'v'; dbuf[1] = 'n';
1.1       hpeyerl   289:                break;
1.3       hpeyerl   290: #endif
1.1       hpeyerl   291:        default:
                    292:                dbuf[0] = dbuf[1] = '?';
                    293:                break;
                    294:        }
                    295:        dbuf[2] = (minor(dev) >> 3) + '0';
                    296:        dbuf[3] = (minor(dev) & 7) + 'a';
                    297:        dbuf[4] = '\0';
                    298:        return (dbuf);
                    299: }
                    300:
                    301: ccdinterleave(cs)
                    302:        register struct ccd_softc *cs;
                    303: {
                    304:        register struct ccdcinfo *ci, *smallci;
                    305:        register struct ccdiinfo *ii;
                    306:        register daddr_t bn, lbn;
                    307:        register int ix;
                    308:        u_long size;
                    309:
                    310: #ifdef DEBUG
1.3       hpeyerl   311:        if (ccddebug & CCDB_INIT)
1.1       hpeyerl   312:                printf("ccdinterleave(%x): ileave %d\n", cs, cs->sc_ileave);
                    313: #endif
                    314:        /*
                    315:         * Allocate an interleave table.
                    316:         * Chances are this is too big, but we don't care.
                    317:         */
                    318:        size = (cs->sc_nccdisks + 1) * sizeof(struct ccdiinfo);
                    319:        cs->sc_itable = (struct ccdiinfo *)malloc(size, M_DEVBUF, M_WAITOK);
                    320:        bzero((caddr_t)cs->sc_itable, size);
                    321:        /*
                    322:         * Trivial case: no interleave (actually interleave of disk size).
                    323:         * Each table entry represent a single component in its entirety.
                    324:         */
                    325:        if (cs->sc_ileave == 0) {
                    326:                bn = 0;
                    327:                ii = cs->sc_itable;
                    328:                for (ix = 0; ix < cs->sc_nccdisks; ix++) {
                    329:                        ii->ii_ndisk = 1;
                    330:                        ii->ii_startblk = bn;
                    331:                        ii->ii_startoff = 0;
                    332:                        ii->ii_index[0] = ix;
                    333:                        bn += cs->sc_cinfo[ix].ci_size;
                    334:                        ii++;
                    335:                }
                    336:                ii->ii_ndisk = 0;
                    337: #ifdef DEBUG
1.3       hpeyerl   338:                if (ccddebug & CCDB_INIT)
1.1       hpeyerl   339:                        printiinfo(cs->sc_itable);
                    340: #endif
                    341:                return(1);
                    342:        }
                    343:        /*
                    344:         * The following isn't fast or pretty; it doesn't have to be.
                    345:         */
                    346:        size = 0;
                    347:        bn = lbn = 0;
                    348:        for (ii = cs->sc_itable; ; ii++) {
                    349:                /*
                    350:                 * Locate the smallest of the remaining components
                    351:                 */
                    352:                smallci = NULL;
                    353:                for (ci = cs->sc_cinfo;
                    354:                     ci < &cs->sc_cinfo[cs->sc_nccdisks]; ci++)
                    355:                        if (ci->ci_size > size &&
                    356:                            (smallci == NULL ||
                    357:                             ci->ci_size < smallci->ci_size))
                    358:                                smallci = ci;
                    359:                /*
                    360:                 * Nobody left, all done
                    361:                 */
                    362:                if (smallci == NULL) {
                    363:                        ii->ii_ndisk = 0;
                    364:                        break;
                    365:                }
                    366:                /*
                    367:                 * Record starting logical block and component offset
                    368:                 */
                    369:                ii->ii_startblk = bn / cs->sc_ileave;
                    370:                ii->ii_startoff = lbn;
                    371:                /*
                    372:                 * Determine how many disks take part in this interleave
                    373:                 * and record their indices.
                    374:                 */
                    375:                ix = 0;
                    376:                for (ci = cs->sc_cinfo;
                    377:                     ci < &cs->sc_cinfo[cs->sc_nccdisks]; ci++)
                    378:                        if (ci->ci_size >= smallci->ci_size)
                    379:                                ii->ii_index[ix++] = ci - cs->sc_cinfo;
                    380:                ii->ii_ndisk = ix;
                    381:                bn += ix * (smallci->ci_size - size);
                    382:                lbn = smallci->ci_size / cs->sc_ileave;
                    383:                size = smallci->ci_size;
                    384:        }
                    385: #ifdef DEBUG
1.3       hpeyerl   386:        if (ccddebug & CCDB_INIT)
1.1       hpeyerl   387:                printiinfo(cs->sc_itable);
                    388: #endif
                    389:        return(1);
                    390: }
                    391:
                    392: #ifdef DEBUG
                    393: printiinfo(ii)
                    394:        struct ccdiinfo *ii;
                    395: {
                    396:        register int ix, i;
                    397:
                    398:        for (ix = 0; ii->ii_ndisk; ix++, ii++) {
                    399:                printf(" itab[%d]: #dk %d sblk %d soff %d",
                    400:                       ix, ii->ii_ndisk, ii->ii_startblk, ii->ii_startoff);
                    401:                for (i = 0; i < ii->ii_ndisk; i++)
                    402:                        printf(" %d", ii->ii_index[i]);
                    403:                printf("\n");
                    404:        }
                    405: }
                    406: #endif
                    407:
                    408: ccdopen(dev, flags)
                    409:        dev_t dev;
                    410: {
                    411:        int unit = ccdunit(dev);
                    412:        register struct ccd_softc *cs = &ccd_softc[unit];
                    413:
                    414: #ifdef DEBUG
1.3       hpeyerl   415:        if (ccddebug & CCDB_FOLLOW)
1.1       hpeyerl   416:                printf("ccdopen(%x, %x)\n", dev, flags);
                    417: #endif
1.3       hpeyerl   418:        if (unit >= numccd || (cs->sc_flags & CCDF_ALIVE) == 0)
1.1       hpeyerl   419:                return(ENXIO);
                    420:        return(0);
                    421: }
                    422:
                    423: ccdstrategy(bp)
                    424:        register struct buf *bp;
                    425: {
                    426:        register int unit = ccdunit(bp->b_dev);
                    427:        register struct ccd_softc *cs = &ccd_softc[unit];
                    428:        register daddr_t bn;
                    429:        register int sz, s;
                    430:
                    431: #ifdef DEBUG
1.3       hpeyerl   432:        if (ccddebug & CCDB_FOLLOW)
1.1       hpeyerl   433:                printf("ccdstrategy(%x): unit %d\n", bp, unit);
                    434: #endif
1.3       hpeyerl   435:        if ((cs->sc_flags & CCDF_INITED) == 0) {
1.1       hpeyerl   436:                bp->b_error = ENXIO;
                    437:                bp->b_flags |= B_ERROR;
                    438:                goto done;
                    439:        }
                    440:        bn = bp->b_blkno;
                    441:        sz = howmany(bp->b_bcount, DEV_BSIZE);
                    442:        if (bn < 0 || bn + sz > cs->sc_size) {
                    443:                sz = cs->sc_size - bn;
                    444:                if (sz == 0) {
                    445:                        bp->b_resid = bp->b_bcount;
                    446:                        goto done;
                    447:                }
                    448:                if (sz < 0) {
                    449:                        bp->b_error = EINVAL;
                    450:                        bp->b_flags |= B_ERROR;
                    451:                        goto done;
                    452:                }
                    453:                bp->b_bcount = dbtob(sz);
                    454:        }
                    455:        bp->b_resid = bp->b_bcount;
                    456:        /*
                    457:         * "Start" the unit.
                    458:         */
                    459:        s = splbio();
1.3       hpeyerl   460:        ccdstart(cs, bp);
1.1       hpeyerl   461:        splx(s);
                    462:        return;
                    463: done:
                    464:        biodone(bp);
                    465: }
                    466:
1.3       hpeyerl   467: ccdstart(cs, bp)
                    468:        register struct ccd_softc *cs;
                    469:        register struct buf *bp;
1.1       hpeyerl   470: {
                    471:        register long bcount, rcount;
                    472:        struct buf *cbp;
                    473:        caddr_t addr;
                    474:        daddr_t bn;
                    475:
                    476: #ifdef DEBUG
1.3       hpeyerl   477:        if (ccddebug & CCDB_FOLLOW)
                    478:                printf("ccdstart(%x, %x)\n", cs, bp);
1.1       hpeyerl   479: #endif
                    480:        /*
                    481:         * Instumentation (not real meaningful)
                    482:         */
                    483:        cs->sc_usecnt++;
                    484:        if (cs->sc_dk >= 0) {
                    485:                dk_busy |= 1 << cs->sc_dk;
                    486:                dk_xfer[cs->sc_dk]++;
                    487:                dk_wds[cs->sc_dk] += bp->b_bcount >> 6;
                    488:        }
                    489:        /*
                    490:         * Allocate component buffers and fire off the requests
                    491:         */
                    492:        bn = bp->b_blkno;
1.3       hpeyerl   493:        addr = bp->b_data;
1.1       hpeyerl   494:        for (bcount = bp->b_bcount; bcount > 0; bcount -= rcount) {
                    495:                cbp = ccdbuffer(cs, bp, bn, addr, bcount);
                    496:                rcount = cbp->b_bcount;
                    497:                (*bdevsw[major(cbp->b_dev)].d_strategy)(cbp);
                    498:                bn += btodb(rcount);
                    499:                addr += rcount;
                    500:        }
                    501: }
                    502:
                    503: /*
                    504:  * Build a component buffer header.
                    505:  */
                    506: struct buf *
                    507: ccdbuffer(cs, bp, bn, addr, bcount)
                    508:        register struct ccd_softc *cs;
                    509:        struct buf *bp;
                    510:        daddr_t bn;
                    511:        caddr_t addr;
                    512:        long bcount;
                    513: {
                    514:        register struct ccdcinfo *ci;
                    515:        register struct buf *cbp;
                    516:        register daddr_t cbn, cboff;
                    517:
                    518: #ifdef DEBUG
1.3       hpeyerl   519:        if (ccddebug & CCDB_IO)
1.1       hpeyerl   520:                printf("ccdbuffer(%x, %x, %d, %x, %d)\n",
                    521:                       cs, bp, bn, addr, bcount);
                    522: #endif
                    523:        /*
                    524:         * Determine which component bn falls in.
                    525:         */
                    526:        cbn = bn;
                    527:        cboff = 0;
                    528:        /*
                    529:         * Serially concatenated
                    530:         */
                    531:        if (cs->sc_ileave == 0) {
                    532:                register daddr_t sblk;
                    533:
                    534:                sblk = 0;
                    535:                for (ci = cs->sc_cinfo; cbn >= sblk + ci->ci_size; ci++)
                    536:                        sblk += ci->ci_size;
                    537:                cbn -= sblk;
                    538:        }
                    539:        /*
                    540:         * Interleaved
                    541:         */
                    542:        else {
                    543:                register struct ccdiinfo *ii;
                    544:                int ccdisk, off;
                    545:
                    546:                cboff = cbn % cs->sc_ileave;
                    547:                cbn /= cs->sc_ileave;
                    548:                for (ii = cs->sc_itable; ii->ii_ndisk; ii++)
                    549:                        if (ii->ii_startblk > cbn)
                    550:                                break;
                    551:                ii--;
                    552:                off = cbn - ii->ii_startblk;
                    553:                if (ii->ii_ndisk == 1) {
                    554:                        ccdisk = ii->ii_index[0];
                    555:                        cbn = ii->ii_startoff + off;
                    556:                } else {
                    557:                        ccdisk = ii->ii_index[off % ii->ii_ndisk];
                    558:                        cbn = ii->ii_startoff + off / ii->ii_ndisk;
                    559:                }
                    560:                cbn *= cs->sc_ileave;
                    561:                ci = &cs->sc_cinfo[ccdisk];
                    562:        }
                    563:        /*
                    564:         * Fill in the component buf structure.
                    565:         */
                    566:        cbp = getcbuf();
                    567:        cbp->b_flags = bp->b_flags | B_CALL;
                    568:        cbp->b_iodone = ccdiodone;
                    569:        cbp->b_proc = bp->b_proc;
                    570:        cbp->b_dev = ci->ci_dev;
                    571:        cbp->b_blkno = cbn + cboff;
1.3       hpeyerl   572:        cbp->b_data = addr;
1.1       hpeyerl   573:        cbp->b_vp = 0;
                    574:        if (cs->sc_ileave == 0)
                    575:                cbp->b_bcount = dbtob(ci->ci_size - cbn);
                    576:        else
                    577:                cbp->b_bcount = dbtob(cs->sc_ileave - cboff);
                    578:        if (cbp->b_bcount > bcount)
                    579:                cbp->b_bcount = bcount;
                    580:        /*
1.3       hpeyerl   581:         * XXX context for ccdiodone
1.1       hpeyerl   582:         */
                    583:        cbp->b_saveaddr = (caddr_t)bp;
                    584:        cbp->b_pfcent = ((cs - ccd_softc) << 16) | (ci - cs->sc_cinfo);
                    585: #ifdef DEBUG
1.3       hpeyerl   586:        if (ccddebug & CCDB_IO)
1.1       hpeyerl   587:                printf(" dev %x(u%d): cbp %x bn %d addr %x bcnt %d\n",
                    588:                       ci->ci_dev, ci-cs->sc_cinfo, cbp, cbp->b_blkno,
1.3       hpeyerl   589:                       cbp->b_data, cbp->b_bcount);
1.1       hpeyerl   590: #endif
                    591:        return(cbp);
                    592: }
                    593:
1.3       hpeyerl   594: ccdintr(cs, bp)
                    595:        register struct ccd_softc *cs;
                    596:        register struct buf *bp;
1.1       hpeyerl   597: {
                    598:
                    599: #ifdef DEBUG
1.3       hpeyerl   600:        if (ccddebug & CCDB_FOLLOW)
                    601:                printf("ccdintr(%x, %x)\n", cs, bp);
1.1       hpeyerl   602: #endif
                    603:        /*
                    604:         * Request is done for better or worse, wakeup the top half.
                    605:         */
                    606:        if (--cs->sc_usecnt == 0 && cs->sc_dk >= 0)
                    607:                dk_busy &= ~(1 << cs->sc_dk);
                    608:        if (bp->b_flags & B_ERROR)
                    609:                bp->b_resid = bp->b_bcount;
                    610:        biodone(bp);
                    611: }
                    612:
                    613: /*
                    614:  * Called by biodone at interrupt time.
                    615:  * Mark the component as done and if all components are done,
                    616:  * take a ccd interrupt.
                    617:  */
1.3       hpeyerl   618: void
1.1       hpeyerl   619: ccdiodone(cbp)
                    620:        register struct buf *cbp;
                    621: {
                    622:        register struct buf *bp = (struct buf *)cbp->b_saveaddr;/* XXX */
                    623:        register int unit = (cbp->b_pfcent >> 16) & 0xFFFF;     /* XXX */
                    624:        int count, s;
                    625:
                    626:        s = splbio();
                    627: #ifdef DEBUG
1.3       hpeyerl   628:        if (ccddebug & CCDB_FOLLOW)
1.1       hpeyerl   629:                printf("ccdiodone(%x)\n", cbp);
1.3       hpeyerl   630:        if (ccddebug & CCDB_IO) {
1.1       hpeyerl   631:                printf("ccdiodone: bp %x bcount %d resid %d\n",
                    632:                       bp, bp->b_bcount, bp->b_resid);
                    633:                printf(" dev %x(u%d), cbp %x bn %d addr %x bcnt %d\n",
                    634:                       cbp->b_dev, cbp->b_pfcent & 0xFFFF, cbp,
1.3       hpeyerl   635:                       cbp->b_blkno, cbp->b_data, cbp->b_bcount);
1.1       hpeyerl   636:        }
                    637: #endif
                    638:
                    639:        if (cbp->b_flags & B_ERROR) {
                    640:                bp->b_flags |= B_ERROR;
                    641:                bp->b_error = biowait(cbp);
                    642: #ifdef DEBUG
                    643:                printf("ccd%d: error %d on component %d\n",
                    644:                       unit, bp->b_error, cbp->b_pfcent & 0xFFFF);
                    645: #endif
                    646:        }
                    647:        count = cbp->b_bcount;
                    648:        putcbuf(cbp);
                    649:
                    650:        /*
                    651:         * If all done, "interrupt".
                    652:         */
                    653:        bp->b_resid -= count;
                    654:        if (bp->b_resid < 0)
                    655:                panic("ccdiodone: count");
1.3       hpeyerl   656:        if (bp->b_resid == 0)
                    657:                ccdintr(&ccd_softc[unit], bp);
1.1       hpeyerl   658:        splx(s);
                    659: }
                    660:
1.3       hpeyerl   661: ccdread(dev, uio)
                    662:        dev_t dev;
                    663:        struct uio *uio;
                    664: {
                    665:        register int unit = ccdunit(dev);
                    666:
                    667: #ifdef DEBUG
                    668:        if (ccddebug & CCDB_FOLLOW)
                    669:                printf("ccdread(%x, %x)\n", dev, uio);
                    670: #endif
                    671:        return(physio(ccdstrategy, NULL, dev, B_READ, minphys, uio));
                    672: }
                    673:
                    674: ccdwrite(dev, uio)
                    675:        dev_t dev;
                    676:        struct uio *uio;
                    677: {
                    678:        register int unit = ccdunit(dev);
                    679:
                    680: #ifdef DEBUG
                    681:        if (ccddebug & CCDB_FOLLOW)
                    682:                printf("ccdwrite(%x, %x)\n", dev, uio);
                    683: #endif
                    684:        return(physio(ccdstrategy, NULL, dev, B_WRITE, minphys, uio));
                    685: }
                    686:
                    687: ccdioctl(dev, cmd, data, flag)
1.1       hpeyerl   688:        dev_t dev;
                    689:        int cmd;
                    690:        caddr_t data;
                    691:        int flag;
                    692: {
                    693:        return(EINVAL);
                    694: }
                    695:
                    696: ccdsize(dev)
                    697:        dev_t dev;
                    698: {
                    699:        int unit = ccdunit(dev);
                    700:        register struct ccd_softc *cs = &ccd_softc[unit];
                    701:
1.3       hpeyerl   702:        if (unit >= numccd || (cs->sc_flags & CCDF_INITED) == 0)
1.1       hpeyerl   703:                return(-1);
                    704:        return(cs->sc_size);
                    705: }
                    706:
                    707: ccddump(dev)
                    708: {
                    709:        return(ENXIO);
                    710: }
                    711: #endif

CVSweb <webmaster@jp.NetBSD.org>