Annotation of kernel/bsd/dev/ccd.c, revision 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.