Annotation of kernel/bsd/dev/ccd.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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