[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.40

1.40    ! thorpej     1: /*     $NetBSD: ccd.c,v 1.39 1997/03/12 22:31:37 mycroft Exp $ */
1.11      thorpej     2:
1.28      thorpej     3: /*-
1.38      thorpej     4:  * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
1.11      thorpej     5:  * All rights reserved.
                      6:  *
1.28      thorpej     7:  * This code is derived from software contributed to The NetBSD Foundation
                      8:  * by Jason R. Thorpe.
                      9:  *
1.11      thorpej    10:  * Redistribution and use in source and binary forms, with or without
                     11:  * modification, are permitted provided that the following conditions
                     12:  * are met:
                     13:  * 1. Redistributions of source code must retain the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer.
                     15:  * 2. Redistributions in binary form must reproduce the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer in the
                     17:  *    documentation and/or other materials provided with the distribution.
                     18:  * 3. All advertising materials mentioning features or use of this software
                     19:  *    must display the following acknowledgement:
1.28      thorpej    20:  *        This product includes software developed by the NetBSD
                     21:  *        Foundation, Inc. and its contributors.
                     22:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     23:  *    contributors may be used to endorse or promote products derived
                     24:  *    from this software without specific prior written permission.
1.11      thorpej    25:  *
1.28      thorpej    26:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     27:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     28:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     29:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
                     30:  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     31:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     32:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     33:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     34:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     35:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     36:  * POSSIBILITY OF SUCH DAMAGE.
1.11      thorpej    37:  */
1.2       cgd        38:
1.1       hpeyerl    39: /*
                     40:  * Copyright (c) 1988 University of Utah.
1.3       hpeyerl    41:  * Copyright (c) 1990, 1993
                     42:  *     The Regents of the University of California.  All rights reserved.
1.1       hpeyerl    43:  *
                     44:  * This code is derived from software contributed to Berkeley by
                     45:  * the Systems Programming Group of the University of Utah Computer
                     46:  * Science Department.
                     47:  *
                     48:  * Redistribution and use in source and binary forms, with or without
                     49:  * modification, are permitted provided that the following conditions
                     50:  * are met:
                     51:  * 1. Redistributions of source code must retain the above copyright
                     52:  *    notice, this list of conditions and the following disclaimer.
                     53:  * 2. Redistributions in binary form must reproduce the above copyright
                     54:  *    notice, this list of conditions and the following disclaimer in the
                     55:  *    documentation and/or other materials provided with the distribution.
                     56:  * 3. All advertising materials mentioning features or use of this software
                     57:  *    must display the following acknowledgement:
                     58:  *     This product includes software developed by the University of
                     59:  *     California, Berkeley and its contributors.
                     60:  * 4. Neither the name of the University nor the names of its contributors
                     61:  *    may be used to endorse or promote products derived from this software
                     62:  *    without specific prior written permission.
                     63:  *
                     64:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     65:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     66:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     67:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     68:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     69:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     70:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     71:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     72:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     73:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     74:  * SUCH DAMAGE.
                     75:  *
1.2       cgd        76:  * from: Utah $Hdr: cd.c 1.6 90/11/28$
                     77:  *
1.3       hpeyerl    78:  *     @(#)cd.c        8.2 (Berkeley) 11/16/93
1.1       hpeyerl    79:  */
                     80:
                     81: /*
                     82:  * "Concatenated" disk driver.
1.11      thorpej    83:  *
                     84:  * Dynamic configuration and disklabel support by:
                     85:  *     Jason R. Thorpe <thorpej@nas.nasa.gov>
                     86:  *     Numerical Aerodynamic Simulation Facility
                     87:  *     Mail Stop 258-6
                     88:  *     NASA Ames Research Center
                     89:  *     Moffett Field, CA 94035
1.24      thorpej    90:  *
                     91:  * Mirroring support based on code written by Satoshi Asami
                     92:  * and Nisha Talagala.
1.1       hpeyerl    93:  */
                     94:
                     95: #include <sys/param.h>
                     96: #include <sys/systm.h>
1.3       hpeyerl    97: #include <sys/proc.h>
1.1       hpeyerl    98: #include <sys/errno.h>
                     99: #include <sys/buf.h>
                    100: #include <sys/malloc.h>
1.11      thorpej   101: #include <sys/namei.h>
1.3       hpeyerl   102: #include <sys/stat.h>
                    103: #include <sys/ioctl.h>
                    104: #include <sys/disklabel.h>
1.11      thorpej   105: #include <sys/device.h>
                    106: #include <sys/disk.h>
                    107: #include <sys/syslog.h>
1.3       hpeyerl   108: #include <sys/fcntl.h>
1.11      thorpej   109: #include <sys/vnode.h>
1.31      christos  110: #include <sys/conf.h>
1.1       hpeyerl   111:
                    112: #include <dev/ccdvar.h>
                    113:
1.11      thorpej   114: #if defined(CCDDEBUG) && !defined(DEBUG)
                    115: #define DEBUG
                    116: #endif
                    117:
1.1       hpeyerl   118: #ifdef DEBUG
1.3       hpeyerl   119: #define CCDB_FOLLOW    0x01
                    120: #define CCDB_INIT      0x02
                    121: #define CCDB_IO                0x04
1.11      thorpej   122: #define CCDB_LABEL     0x08
                    123: #define CCDB_VNODE     0x10
1.24      thorpej   124: int ccddebug = 0x00;
1.1       hpeyerl   125: #endif
                    126:
1.6       cgd       127: #define        ccdunit(x)      DISKUNIT(x)
                    128:
                    129: struct ccdbuf {
                    130:        struct buf      cb_buf;         /* new I/O buf */
                    131:        struct buf      *cb_obp;        /* ptr. to original I/O buf */
                    132:        int             cb_unit;        /* target unit */
                    133:        int             cb_comp;        /* target component */
1.24      thorpej   134:        int             cb_flags;       /* misc. flags */
1.38      thorpej   135:        LIST_ENTRY(ccdbuf) cb_list;     /* entry on freelist */
                    136: };
1.24      thorpej   137:
1.38      thorpej   138: /* cb_flags */
1.24      thorpej   139: #define CBF_MIRROR     0x01            /* we're for a mirror component */
1.6       cgd       140:
1.38      thorpej   141: /*
                    142:  * Number of freelist buffers per component.  Overridable in kernel
                    143:  * config file and patchable.
                    144:  */
                    145: #ifndef CCDNBUF
                    146: #define        CCDNBUF         8
                    147: #endif
                    148: int    ccdnbuf = CCDNBUF;
                    149:
                    150: /*
                    151:  * XXX Is it OK to wait here?
                    152:  * XXX maybe set up a timeout when we hit some lowater?
                    153:  * XXX    --thorpej
                    154:  */
                    155: #define        CCDGETBUF(cs, cbp)      do {                                    \
                    156:                (cs)->sc_ngetbuf++;                                     \
                    157:                if (((cbp) = (cs)->sc_freelist.lh_first) != NULL) {     \
                    158:                        LIST_REMOVE((cbp), cb_list);                    \
                    159:                        (cs)->sc_freecount--;                           \
                    160:                } else {                                                \
                    161:                        (cs)->sc_nmisses++;                             \
                    162:                        MALLOC((cbp), struct ccdbuf *,                  \
                    163:                            sizeof(struct ccdbuf), M_DEVBUF, M_WAITOK); \
                    164:                }                                                       \
                    165:        } while (0)
                    166:
                    167: #define        CCDPUTBUF(cs, cbp)      do {                                    \
                    168:                if ((cs)->sc_freecount == (cs)->sc_hiwat) {             \
                    169:                        FREE((cbp), M_DEVBUF);                          \
                    170:                } else {                                                \
                    171:                        LIST_INSERT_HEAD(&(cs)->sc_freelist, (cbp), cb_list); \
                    172:                        (cs)->sc_freecount++;                           \
                    173:                }                                                       \
                    174:        } while (0)
1.1       hpeyerl   175:
1.11      thorpej   176: #define CCDLABELDEV(dev)       \
                    177:        (MAKEDISKDEV(major((dev)), ccdunit((dev)), RAW_PART))
1.1       hpeyerl   178:
1.11      thorpej   179: /* called by main() at boot time */
                    180: void   ccdattach __P((int));
                    181:
                    182: /* called by biodone() at interrupt time */
1.29      christos  183: void   ccdiodone __P((struct buf *));
                    184: int    ccdsize __P((dev_t));
1.11      thorpej   185:
                    186: static void ccdstart __P((struct ccd_softc *, struct buf *));
                    187: static void ccdinterleave __P((struct ccd_softc *, int));
                    188: static void ccdintr __P((struct ccd_softc *, struct buf *));
                    189: static int ccdinit __P((struct ccddevice *, char **, struct proc *));
                    190: static int ccdlookup __P((char *, struct proc *p, struct vnode **));
1.24      thorpej   191: static void ccdbuffer __P((struct ccd_softc *, struct buf *,
                    192:                daddr_t, caddr_t, long, struct ccdbuf **));
1.11      thorpej   193: static void ccdgetdisklabel __P((dev_t));
                    194: static void ccdmakedisklabel __P((struct ccd_softc *));
1.15      thorpej   195: static int ccdlock __P((struct ccd_softc *));
                    196: static void ccdunlock __P((struct ccd_softc *));
1.3       hpeyerl   197:
1.11      thorpej   198: #ifdef DEBUG
                    199: static void printiinfo __P((struct ccdiinfo *));
                    200: #endif
                    201:
                    202: /* Non-private for the benefit of libkvm. */
                    203: struct ccd_softc *ccd_softc;
                    204: struct ccddevice *ccddevs;
                    205: int    numccd = 0;
1.1       hpeyerl   206:
1.3       hpeyerl   207: /*
1.11      thorpej   208:  * Called by main() during pseudo-device attachment.  All we need
                    209:  * to do is allocate enough space for devices to be configured later.
1.1       hpeyerl   210:  */
                    211: void
1.3       hpeyerl   212: ccdattach(num)
                    213:        int num;
                    214: {
1.11      thorpej   215:        if (num <= 0) {
                    216: #ifdef DIAGNOSTIC
                    217:                panic("ccdattach: count <= 0");
                    218: #endif
1.3       hpeyerl   219:                return;
1.11      thorpej   220:        }
                    221:
                    222:        ccd_softc = (struct ccd_softc *)malloc(num * sizeof(struct ccd_softc),
                    223:            M_DEVBUF, M_NOWAIT);
                    224:        ccddevs = (struct ccddevice *)malloc(num * sizeof(struct ccddevice),
                    225:            M_DEVBUF, M_NOWAIT);
                    226:        if ((ccd_softc == NULL) || (ccddevs == NULL)) {
1.35      christos  227:                printf("WARNING: no memory for concatenated disks\n");
1.11      thorpej   228:                if (ccd_softc != NULL)
                    229:                        free(ccd_softc, M_DEVBUF);
                    230:                if (ccddevs != NULL)
                    231:                        free(ccddevs, M_DEVBUF);
1.3       hpeyerl   232:                return;
                    233:        }
                    234:        numccd = num;
1.11      thorpej   235:        bzero(ccd_softc, num * sizeof(struct ccd_softc));
                    236:        bzero(ccddevs, num * sizeof(struct ccddevice));
1.1       hpeyerl   237: }
                    238:
1.11      thorpej   239: static int
                    240: ccdinit(ccd, cpaths, p)
1.1       hpeyerl   241:        struct ccddevice *ccd;
1.11      thorpej   242:        char **cpaths;
                    243:        struct proc *p;
1.1       hpeyerl   244: {
                    245:        register struct ccd_softc *cs = &ccd_softc[ccd->ccd_unit];
1.29      christos  246:        register struct ccdcinfo *ci = NULL;
1.1       hpeyerl   247:        register size_t size;
                    248:        register int ix;
1.11      thorpej   249:        struct vnode *vp;
                    250:        struct vattr va;
1.1       hpeyerl   251:        size_t minsize;
1.11      thorpej   252:        int maxsecsize;
1.7       cgd       253:        struct partinfo dpart;
1.11      thorpej   254:        struct ccdgeom *ccg = &cs->sc_geom;
                    255:        char tmppath[MAXPATHLEN];
1.38      thorpej   256:        struct ccdbuf *cbp;
1.11      thorpej   257:        int error;
1.1       hpeyerl   258:
                    259: #ifdef DEBUG
1.3       hpeyerl   260:        if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))
1.35      christos  261:                printf("ccdinit: unit %d\n", ccd->ccd_unit);
1.1       hpeyerl   262: #endif
1.11      thorpej   263:
1.1       hpeyerl   264:        cs->sc_size = 0;
                    265:        cs->sc_ileave = ccd->ccd_interleave;
1.11      thorpej   266:        cs->sc_nccdisks = ccd->ccd_ndev;
1.35      christos  267:        sprintf(cs->sc_xname, "ccd%d", ccd->ccd_unit);  /* XXX */
1.11      thorpej   268:
                    269:        /* Allocate space for the component info. */
                    270:        cs->sc_cinfo = malloc(cs->sc_nccdisks * sizeof(struct ccdcinfo),
                    271:            M_DEVBUF, M_WAITOK);
                    272:
1.1       hpeyerl   273:        /*
                    274:         * Verify that each component piece exists and record
                    275:         * relevant information about it.
                    276:         */
1.11      thorpej   277:        maxsecsize = 0;
1.1       hpeyerl   278:        minsize = 0;
1.11      thorpej   279:        for (ix = 0; ix < cs->sc_nccdisks; ix++) {
                    280:                vp = ccd->ccd_vpp[ix];
1.1       hpeyerl   281:                ci = &cs->sc_cinfo[ix];
1.11      thorpej   282:                ci->ci_vp = vp;
                    283:
                    284:                /*
                    285:                 * Copy in the pathname of the component.
                    286:                 */
                    287:                bzero(tmppath, sizeof(tmppath));        /* sanity */
1.29      christos  288:                error = copyinstr(cpaths[ix], tmppath,
                    289:                    MAXPATHLEN, &ci->ci_pathlen);
                    290:                if (error) {
1.11      thorpej   291: #ifdef DEBUG
                    292:                        if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))
1.35      christos  293:                                printf("%s: can't copy path, error = %d\n",
1.23      thorpej   294:                                    cs->sc_xname, error);
1.11      thorpej   295: #endif
                    296:                        free(cs->sc_cinfo, M_DEVBUF);
                    297:                        return (error);
                    298:                }
                    299:                ci->ci_path = malloc(ci->ci_pathlen, M_DEVBUF, M_WAITOK);
                    300:                bcopy(tmppath, ci->ci_path, ci->ci_pathlen);
                    301:
                    302:                /*
                    303:                 * XXX: Cache the component's dev_t.
                    304:                 */
1.29      christos  305:                if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)) != 0) {
1.11      thorpej   306: #ifdef DEBUG
                    307:                        if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))
1.35      christos  308:                                printf("%s: %s: getattr failed %s = %d\n",
1.23      thorpej   309:                                    cs->sc_xname, ci->ci_path,
1.11      thorpej   310:                                    "error", error);
                    311: #endif
                    312:                        free(ci->ci_path, M_DEVBUF);
                    313:                        free(cs->sc_cinfo, M_DEVBUF);
                    314:                        return (error);
                    315:                }
                    316:                ci->ci_dev = va.va_rdev;
                    317:
1.3       hpeyerl   318:                /*
1.11      thorpej   319:                 * Get partition information for the component.
1.3       hpeyerl   320:                 */
1.29      christos  321:                error = VOP_IOCTL(vp, DIOCGPART, (caddr_t)&dpart,
                    322:                    FREAD, p->p_ucred, p);
                    323:                if (error) {
1.11      thorpej   324: #ifdef DEBUG
                    325:                        if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))
1.35      christos  326:                                 printf("%s: %s: ioctl failed, error = %d\n",
1.23      thorpej   327:                                     cs->sc_xname, ci->ci_path, error);
1.11      thorpej   328: #endif
                    329:                        free(ci->ci_path, M_DEVBUF);
                    330:                        free(cs->sc_cinfo, M_DEVBUF);
                    331:                        return (error);
                    332:                }
                    333:                if (dpart.part->p_fstype == FS_BSDFFS) {
                    334:                        maxsecsize =
                    335:                            ((dpart.disklab->d_secsize > maxsecsize) ?
                    336:                            dpart.disklab->d_secsize : maxsecsize);
                    337:                        size = dpart.part->p_size;
                    338:                } else {
                    339: #ifdef DEBUG
                    340:                        if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))
1.35      christos  341:                                printf("%s: %s: incorrect partition type\n",
1.23      thorpej   342:                                    cs->sc_xname, ci->ci_path);
1.11      thorpej   343: #endif
                    344:                        free(ci->ci_path, M_DEVBUF);
                    345:                        free(cs->sc_cinfo, M_DEVBUF);
                    346:                        return (EFTYPE);
                    347:                }
1.7       cgd       348:
1.11      thorpej   349:                /*
                    350:                 * Calculate the size, truncating to an interleave
                    351:                 * boundary if necessary.
                    352:                 */
1.1       hpeyerl   353:                if (cs->sc_ileave > 1)
                    354:                        size -= size % cs->sc_ileave;
1.11      thorpej   355:
1.1       hpeyerl   356:                if (size == 0) {
1.11      thorpej   357: #ifdef DEBUG
                    358:                        if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))
1.35      christos  359:                                printf("%s: %s: size == 0\n",
1.23      thorpej   360:                                    cs->sc_xname, ci->ci_path);
1.11      thorpej   361: #endif
                    362:                        free(ci->ci_path, M_DEVBUF);
                    363:                        free(cs->sc_cinfo, M_DEVBUF);
                    364:                        return (ENODEV);
1.3       hpeyerl   365:                }
1.11      thorpej   366:
1.1       hpeyerl   367:                if (minsize == 0 || size < minsize)
                    368:                        minsize = size;
                    369:                ci->ci_size = size;
                    370:                cs->sc_size += size;
                    371:        }
1.11      thorpej   372:
                    373:        /*
                    374:         * Don't allow the interleave to be smaller than
                    375:         * the biggest component sector.
                    376:         */
                    377:        if ((cs->sc_ileave > 0) &&
                    378:            (cs->sc_ileave < (maxsecsize / DEV_BSIZE))) {
                    379: #ifdef DEBUG
                    380:                if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))
1.35      christos  381:                        printf("%s: interleave must be at least %d\n",
1.23      thorpej   382:                            cs->sc_xname, (maxsecsize / DEV_BSIZE));
1.11      thorpej   383: #endif
                    384:                free(ci->ci_path, M_DEVBUF);
                    385:                free(cs->sc_cinfo, M_DEVBUF);
                    386:                return (EINVAL);
                    387:        }
                    388:
1.1       hpeyerl   389:        /*
1.24      thorpej   390:         * Mirroring support requires uniform interleave and
                    391:         * and even number of components.
                    392:         */
                    393:        if (ccd->ccd_flags & CCDF_MIRROR) {
                    394:                ccd->ccd_flags |= CCDF_UNIFORM;
                    395:                if (cs->sc_ileave == 0) {
                    396: #ifdef DEBUG
                    397:                        if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))
1.35      christos  398:                        printf("%s: mirroring requires interleave\n",
1.25      thorpej   399:                            cs->sc_xname);
1.24      thorpej   400: #endif
                    401:                        free(ci->ci_path, M_DEVBUF);
                    402:                        free(cs->sc_cinfo, M_DEVBUF);
                    403:                        return (EINVAL);
                    404:                }
                    405:                if (cs->sc_nccdisks % 2) {
                    406: #ifdef DEBUG
                    407:                        if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))
1.35      christos  408:                        printf("%s: mirroring requires even # of components\n",
1.24      thorpej   409:                            cs->sc_xname);
                    410: #endif
                    411:                        free(ci->ci_path, M_DEVBUF);
                    412:                        free(cs->sc_cinfo, M_DEVBUF);
                    413:                        return (EINVAL);
                    414:                }
                    415:        }
                    416:
                    417:        /*
1.1       hpeyerl   418:         * If uniform interleave is desired set all sizes to that of
                    419:         * the smallest component.
                    420:         */
1.3       hpeyerl   421:        if (ccd->ccd_flags & CCDF_UNIFORM) {
1.1       hpeyerl   422:                for (ci = cs->sc_cinfo;
                    423:                     ci < &cs->sc_cinfo[cs->sc_nccdisks]; ci++)
                    424:                        ci->ci_size = minsize;
1.24      thorpej   425:
                    426:                if (ccd->ccd_flags & CCDF_MIRROR)
                    427:                        cs->sc_size = (cs->sc_nccdisks / 2) * minsize;
                    428:                else
                    429:                        cs->sc_size = cs->sc_nccdisks * minsize;
1.1       hpeyerl   430:        }
1.11      thorpej   431:
                    432:        /*
                    433:         * Construct the interleave table.
                    434:         */
                    435:        ccdinterleave(cs, ccd->ccd_unit);
                    436:
1.1       hpeyerl   437:        /*
1.11      thorpej   438:         * Create pseudo-geometry based on 1MB cylinders.  It's
                    439:         * pretty close.
1.1       hpeyerl   440:         */
1.11      thorpej   441:        ccg->ccg_secsize = DEV_BSIZE;
1.19      thorpej   442:        ccg->ccg_ntracks = 1;
1.11      thorpej   443:        ccg->ccg_nsectors = 1024 * (1024 / ccg->ccg_secsize);
                    444:        ccg->ccg_ncylinders = cs->sc_size / ccg->ccg_nsectors;
                    445:
1.38      thorpej   446:        /*
                    447:         * Allocate the component buffer header freelist.  We allocate
                    448:         * ccdnbuf buffers per component.
                    449:         */
                    450:        LIST_INIT(&cs->sc_freelist);
                    451:        cs->sc_hiwat = cs->sc_nccdisks * ccdnbuf;
                    452:        cs->sc_freecount = cs->sc_hiwat;
                    453:        for (ix = 0; ix < cs->sc_hiwat; ix++) {
                    454:                MALLOC(cbp, struct ccdbuf *, sizeof(struct ccdbuf),
                    455:                    M_DEVBUF, M_WAITOK);
                    456:                LIST_INSERT_HEAD(&cs->sc_freelist, cbp, cb_list);
                    457:        }
                    458:
                    459:        /* Reset statistics. */
                    460:        cs->sc_nmisses = 0;
                    461:        cs->sc_ngetbuf = 0;
                    462:
1.11      thorpej   463:        cs->sc_flags |= CCDF_INITED;
                    464:        cs->sc_cflags = ccd->ccd_flags; /* So we can find out later... */
                    465:        cs->sc_unit = ccd->ccd_unit;
1.23      thorpej   466:
1.11      thorpej   467:        return (0);
1.1       hpeyerl   468: }
                    469:
1.11      thorpej   470: static void
                    471: ccdinterleave(cs, unit)
1.1       hpeyerl   472:        register struct ccd_softc *cs;
1.11      thorpej   473:        int unit;
1.1       hpeyerl   474: {
                    475:        register struct ccdcinfo *ci, *smallci;
                    476:        register struct ccdiinfo *ii;
                    477:        register daddr_t bn, lbn;
                    478:        register int ix;
                    479:        u_long size;
                    480:
                    481: #ifdef DEBUG
1.3       hpeyerl   482:        if (ccddebug & CCDB_INIT)
1.35      christos  483:                printf("ccdinterleave(%p): ileave %d\n", cs, cs->sc_ileave);
1.1       hpeyerl   484: #endif
                    485:        /*
                    486:         * Allocate an interleave table.
                    487:         * Chances are this is too big, but we don't care.
                    488:         */
                    489:        size = (cs->sc_nccdisks + 1) * sizeof(struct ccdiinfo);
                    490:        cs->sc_itable = (struct ccdiinfo *)malloc(size, M_DEVBUF, M_WAITOK);
                    491:        bzero((caddr_t)cs->sc_itable, size);
1.11      thorpej   492:
1.1       hpeyerl   493:        /*
                    494:         * Trivial case: no interleave (actually interleave of disk size).
1.11      thorpej   495:         * Each table entry represents a single component in its entirety.
1.1       hpeyerl   496:         */
                    497:        if (cs->sc_ileave == 0) {
                    498:                bn = 0;
                    499:                ii = cs->sc_itable;
1.11      thorpej   500:
1.1       hpeyerl   501:                for (ix = 0; ix < cs->sc_nccdisks; ix++) {
1.19      thorpej   502:                        /* Allocate space for ii_index. */
                    503:                        ii->ii_index = malloc(sizeof(int), M_DEVBUF, M_WAITOK);
1.1       hpeyerl   504:                        ii->ii_ndisk = 1;
                    505:                        ii->ii_startblk = bn;
                    506:                        ii->ii_startoff = 0;
                    507:                        ii->ii_index[0] = ix;
                    508:                        bn += cs->sc_cinfo[ix].ci_size;
                    509:                        ii++;
                    510:                }
                    511:                ii->ii_ndisk = 0;
                    512: #ifdef DEBUG
1.3       hpeyerl   513:                if (ccddebug & CCDB_INIT)
1.1       hpeyerl   514:                        printiinfo(cs->sc_itable);
                    515: #endif
1.11      thorpej   516:                return;
1.1       hpeyerl   517:        }
1.11      thorpej   518:
1.1       hpeyerl   519:        /*
                    520:         * The following isn't fast or pretty; it doesn't have to be.
                    521:         */
                    522:        size = 0;
                    523:        bn = lbn = 0;
                    524:        for (ii = cs->sc_itable; ; ii++) {
1.11      thorpej   525:                /* Allocate space for ii_index. */
1.19      thorpej   526:                ii->ii_index = malloc((sizeof(int) * cs->sc_nccdisks),
                    527:                    M_DEVBUF, M_WAITOK);
1.11      thorpej   528:
1.1       hpeyerl   529:                /*
                    530:                 * Locate the smallest of the remaining components
                    531:                 */
                    532:                smallci = NULL;
                    533:                for (ci = cs->sc_cinfo;
                    534:                     ci < &cs->sc_cinfo[cs->sc_nccdisks]; ci++)
                    535:                        if (ci->ci_size > size &&
                    536:                            (smallci == NULL ||
                    537:                             ci->ci_size < smallci->ci_size))
                    538:                                smallci = ci;
1.11      thorpej   539:
1.1       hpeyerl   540:                /*
                    541:                 * Nobody left, all done
                    542:                 */
                    543:                if (smallci == NULL) {
                    544:                        ii->ii_ndisk = 0;
                    545:                        break;
                    546:                }
1.11      thorpej   547:
1.1       hpeyerl   548:                /*
                    549:                 * Record starting logical block and component offset
                    550:                 */
                    551:                ii->ii_startblk = bn / cs->sc_ileave;
                    552:                ii->ii_startoff = lbn;
1.11      thorpej   553:
1.1       hpeyerl   554:                /*
                    555:                 * Determine how many disks take part in this interleave
                    556:                 * and record their indices.
                    557:                 */
                    558:                ix = 0;
                    559:                for (ci = cs->sc_cinfo;
                    560:                     ci < &cs->sc_cinfo[cs->sc_nccdisks]; ci++)
                    561:                        if (ci->ci_size >= smallci->ci_size)
                    562:                                ii->ii_index[ix++] = ci - cs->sc_cinfo;
                    563:                ii->ii_ndisk = ix;
                    564:                bn += ix * (smallci->ci_size - size);
                    565:                lbn = smallci->ci_size / cs->sc_ileave;
                    566:                size = smallci->ci_size;
                    567:        }
                    568: #ifdef DEBUG
1.3       hpeyerl   569:        if (ccddebug & CCDB_INIT)
1.1       hpeyerl   570:                printiinfo(cs->sc_itable);
                    571: #endif
                    572: }
                    573:
1.11      thorpej   574: /* ARGSUSED */
                    575: int
                    576: ccdopen(dev, flags, fmt, p)
1.1       hpeyerl   577:        dev_t dev;
1.11      thorpej   578:        int flags, fmt;
                    579:        struct proc *p;
1.1       hpeyerl   580: {
                    581:        int unit = ccdunit(dev);
1.11      thorpej   582:        struct ccd_softc *cs;
                    583:        struct disklabel *lp;
1.15      thorpej   584:        int error = 0, part, pmask;
1.1       hpeyerl   585:
                    586: #ifdef DEBUG
1.3       hpeyerl   587:        if (ccddebug & CCDB_FOLLOW)
1.35      christos  588:                printf("ccdopen(%x, %x)\n", dev, flags);
1.1       hpeyerl   589: #endif
1.11      thorpej   590:        if (unit >= numccd)
                    591:                return (ENXIO);
                    592:        cs = &ccd_softc[unit];
1.15      thorpej   593:
1.29      christos  594:        if ((error = ccdlock(cs)) != 0)
1.15      thorpej   595:                return (error);
                    596:
1.23      thorpej   597:        lp = cs->sc_dkdev.dk_label;
1.11      thorpej   598:
                    599:        part = DISKPART(dev);
                    600:        pmask = (1 << part);
                    601:
1.15      thorpej   602:        /*
                    603:         * If we're initialized, check to see if there are any other
                    604:         * open partitions.  If not, then it's safe to update
                    605:         * the in-core disklabel.
                    606:         */
                    607:        if ((cs->sc_flags & CCDF_INITED) && (cs->sc_dkdev.dk_openmask == 0))
                    608:                ccdgetdisklabel(dev);
                    609:
1.11      thorpej   610:        /* Check that the partition exists. */
1.27      thorpej   611:        if (part != RAW_PART) {
                    612:                if (((cs->sc_flags & CCDF_INITED) == 0) ||
1.37      thorpej   613:                    ((part >= lp->d_npartitions) ||
1.27      thorpej   614:                     (lp->d_partitions[part].p_fstype == FS_UNUSED))) {
                    615:                        error = ENXIO;
                    616:                        goto done;
                    617:                }
1.15      thorpej   618:        }
1.11      thorpej   619:
                    620:        /* Prevent our unit from being unconfigured while open. */
                    621:        switch (fmt) {
                    622:        case S_IFCHR:
                    623:                cs->sc_dkdev.dk_copenmask |= pmask;
                    624:                break;
                    625:
                    626:        case S_IFBLK:
                    627:                cs->sc_dkdev.dk_bopenmask |= pmask;
                    628:                break;
                    629:        }
                    630:        cs->sc_dkdev.dk_openmask =
                    631:            cs->sc_dkdev.dk_copenmask | cs->sc_dkdev.dk_bopenmask;
                    632:
1.15      thorpej   633:  done:
                    634:        ccdunlock(cs);
1.33      thorpej   635:        return (error);
1.7       cgd       636: }
                    637:
1.11      thorpej   638: /* ARGSUSED */
                    639: int
                    640: ccdclose(dev, flags, fmt, p)
1.7       cgd       641:        dev_t dev;
1.11      thorpej   642:        int flags, fmt;
                    643:        struct proc *p;
1.7       cgd       644: {
1.11      thorpej   645:        int unit = ccdunit(dev);
                    646:        struct ccd_softc *cs;
1.15      thorpej   647:        int error = 0, part;
1.11      thorpej   648:
1.7       cgd       649: #ifdef DEBUG
                    650:        if (ccddebug & CCDB_FOLLOW)
1.35      christos  651:                printf("ccdclose(%x, %x)\n", dev, flags);
1.7       cgd       652: #endif
1.11      thorpej   653:
                    654:        if (unit >= numccd)
                    655:                return (ENXIO);
                    656:        cs = &ccd_softc[unit];
1.15      thorpej   657:
1.29      christos  658:        if ((error = ccdlock(cs)) != 0)
1.15      thorpej   659:                return (error);
                    660:
1.11      thorpej   661:        part = DISKPART(dev);
                    662:
                    663:        /* ...that much closer to allowing unconfiguration... */
                    664:        switch (fmt) {
                    665:        case S_IFCHR:
                    666:                cs->sc_dkdev.dk_copenmask &= ~(1 << part);
                    667:                break;
                    668:
                    669:        case S_IFBLK:
                    670:                cs->sc_dkdev.dk_bopenmask &= ~(1 << part);
                    671:                break;
                    672:        }
                    673:        cs->sc_dkdev.dk_openmask =
                    674:            cs->sc_dkdev.dk_copenmask | cs->sc_dkdev.dk_bopenmask;
                    675:
1.15      thorpej   676:        ccdunlock(cs);
1.7       cgd       677:        return (0);
1.1       hpeyerl   678: }
                    679:
1.11      thorpej   680: void
1.1       hpeyerl   681: ccdstrategy(bp)
                    682:        register struct buf *bp;
                    683: {
                    684:        register int unit = ccdunit(bp->b_dev);
                    685:        register struct ccd_softc *cs = &ccd_softc[unit];
1.29      christos  686:        register int s;
1.11      thorpej   687:        int wlabel;
1.15      thorpej   688:        struct disklabel *lp;
1.1       hpeyerl   689:
                    690: #ifdef DEBUG
1.3       hpeyerl   691:        if (ccddebug & CCDB_FOLLOW)
1.35      christos  692:                printf("ccdstrategy(%p): unit %d\n", bp, unit);
1.1       hpeyerl   693: #endif
1.3       hpeyerl   694:        if ((cs->sc_flags & CCDF_INITED) == 0) {
1.1       hpeyerl   695:                bp->b_error = ENXIO;
                    696:                bp->b_flags |= B_ERROR;
                    697:                goto done;
                    698:        }
1.11      thorpej   699:
                    700:        /* If it's a nil transfer, wake up the top half now. */
                    701:        if (bp->b_bcount == 0)
                    702:                goto done;
                    703:
1.23      thorpej   704:        lp = cs->sc_dkdev.dk_label;
1.15      thorpej   705:
1.11      thorpej   706:        /*
1.17      thorpej   707:         * Do bounds checking and adjust transfer.  If there's an
1.11      thorpej   708:         * error, the bounds check will flag that for us.
                    709:         */
                    710:        wlabel = cs->sc_flags & (CCDF_WLABEL|CCDF_LABELLING);
1.16      thorpej   711:        if (DISKPART(bp->b_dev) != RAW_PART)
1.15      thorpej   712:                if (bounds_check_with_label(bp, lp, wlabel) <= 0)
1.1       hpeyerl   713:                        goto done;
1.11      thorpej   714:
1.1       hpeyerl   715:        bp->b_resid = bp->b_bcount;
1.11      thorpej   716:
1.1       hpeyerl   717:        /*
                    718:         * "Start" the unit.
                    719:         */
                    720:        s = splbio();
1.3       hpeyerl   721:        ccdstart(cs, bp);
1.1       hpeyerl   722:        splx(s);
                    723:        return;
                    724: done:
                    725:        biodone(bp);
                    726: }
                    727:
1.11      thorpej   728: static void
1.3       hpeyerl   729: ccdstart(cs, bp)
                    730:        register struct ccd_softc *cs;
                    731:        register struct buf *bp;
1.1       hpeyerl   732: {
                    733:        register long bcount, rcount;
1.24      thorpej   734:        struct ccdbuf *cbp[4];
1.1       hpeyerl   735:        caddr_t addr;
                    736:        daddr_t bn;
1.20      thorpej   737:        struct partition *pp;
1.1       hpeyerl   738:
                    739: #ifdef DEBUG
1.3       hpeyerl   740:        if (ccddebug & CCDB_FOLLOW)
1.35      christos  741:                printf("ccdstart(%p, %p)\n", cs, bp);
1.1       hpeyerl   742: #endif
1.11      thorpej   743:
1.23      thorpej   744:        /* Instrumentation. */
                    745:        disk_busy(&cs->sc_dkdev);
1.11      thorpej   746:
1.1       hpeyerl   747:        /*
1.17      thorpej   748:         * Translate the partition-relative block number to an absolute.
1.1       hpeyerl   749:         */
1.20      thorpej   750:        bn = bp->b_blkno;
                    751:        if (DISKPART(bp->b_dev) != RAW_PART) {
1.23      thorpej   752:                pp = &cs->sc_dkdev.dk_label->d_partitions[DISKPART(bp->b_dev)];
1.20      thorpej   753:                bn += pp->p_offset;
                    754:        }
1.17      thorpej   755:
                    756:        /*
                    757:         * Allocate component buffers and fire off the requests
                    758:         */
1.3       hpeyerl   759:        addr = bp->b_data;
1.1       hpeyerl   760:        for (bcount = bp->b_bcount; bcount > 0; bcount -= rcount) {
1.24      thorpej   761:                ccdbuffer(cs, bp, bn, addr, bcount, cbp);
                    762:                rcount = cbp[0]->cb_buf.b_bcount;
                    763:                if ((cbp[0]->cb_buf.b_flags & B_READ) == 0)
                    764:                        cbp[0]->cb_buf.b_vp->v_numoutput++;
                    765:                VOP_STRATEGY(&cbp[0]->cb_buf);
                    766:
                    767:                /*
                    768:                 * Mirror requires additional write.
                    769:                 */
                    770:                if ((cs->sc_cflags & CCDF_MIRROR) &&
                    771:                    ((cbp[0]->cb_buf.b_flags & B_READ) == 0)) {
                    772:                        cbp[1]->cb_buf.b_vp->v_numoutput++;
                    773:                        VOP_STRATEGY(&cbp[1]->cb_buf);
                    774:                }
                    775:
1.1       hpeyerl   776:                bn += btodb(rcount);
                    777:                addr += rcount;
                    778:        }
                    779: }
                    780:
                    781: /*
                    782:  * Build a component buffer header.
                    783:  */
1.24      thorpej   784: static void
                    785: ccdbuffer(cs, bp, bn, addr, bcount, cbpp)
1.1       hpeyerl   786:        register struct ccd_softc *cs;
                    787:        struct buf *bp;
                    788:        daddr_t bn;
                    789:        caddr_t addr;
                    790:        long bcount;
1.24      thorpej   791:        struct ccdbuf **cbpp;
1.1       hpeyerl   792: {
1.29      christos  793:        register struct ccdcinfo *ci, *ci2 = NULL;
1.6       cgd       794:        register struct ccdbuf *cbp;
1.1       hpeyerl   795:        register daddr_t cbn, cboff;
1.36      thorpej   796:        int ccdisk;
1.1       hpeyerl   797:
                    798: #ifdef DEBUG
1.3       hpeyerl   799:        if (ccddebug & CCDB_IO)
1.35      christos  800:                printf("ccdbuffer(%p, %p, %d, %p, %ld)\n",
1.1       hpeyerl   801:                       cs, bp, bn, addr, bcount);
                    802: #endif
                    803:        /*
                    804:         * Determine which component bn falls in.
                    805:         */
                    806:        cbn = bn;
                    807:        cboff = 0;
1.11      thorpej   808:
1.1       hpeyerl   809:        /*
                    810:         * Serially concatenated
                    811:         */
                    812:        if (cs->sc_ileave == 0) {
                    813:                register daddr_t sblk;
                    814:
                    815:                sblk = 0;
1.36      thorpej   816:                for (ccdisk = 0, ci = &cs->sc_cinfo[ccdisk];
                    817:                    cbn >= sblk + ci->ci_size;
                    818:                    ccdisk++, ci = &cs->sc_cinfo[ccdisk])
1.1       hpeyerl   819:                        sblk += ci->ci_size;
                    820:                cbn -= sblk;
                    821:        }
                    822:        /*
                    823:         * Interleaved
                    824:         */
                    825:        else {
                    826:                register struct ccdiinfo *ii;
1.36      thorpej   827:                int off;
1.1       hpeyerl   828:
                    829:                cboff = cbn % cs->sc_ileave;
                    830:                cbn /= cs->sc_ileave;
                    831:                for (ii = cs->sc_itable; ii->ii_ndisk; ii++)
                    832:                        if (ii->ii_startblk > cbn)
                    833:                                break;
                    834:                ii--;
                    835:                off = cbn - ii->ii_startblk;
                    836:                if (ii->ii_ndisk == 1) {
                    837:                        ccdisk = ii->ii_index[0];
                    838:                        cbn = ii->ii_startoff + off;
                    839:                } else {
1.24      thorpej   840:                        if (cs->sc_cflags & CCDF_MIRROR) {
                    841:                                ccdisk =
                    842:                                    ii->ii_index[off % (ii->ii_ndisk / 2)];
                    843:                                cbn = ii->ii_startoff +
                    844:                                    (off / (ii->ii_ndisk / 2));
                    845:                                /* Mirrored data */
                    846:                                ci2 =
                    847:                                    &cs->sc_cinfo[ccdisk + (ii->ii_ndisk / 2)];
                    848:                        } else {
                    849:                                /* Normal case. */
                    850:                                ccdisk = ii->ii_index[off % ii->ii_ndisk];
                    851:                                cbn = ii->ii_startoff + off / ii->ii_ndisk;
                    852:                        }
1.1       hpeyerl   853:                }
                    854:                cbn *= cs->sc_ileave;
                    855:                ci = &cs->sc_cinfo[ccdisk];
                    856:        }
1.11      thorpej   857:
1.1       hpeyerl   858:        /*
                    859:         * Fill in the component buf structure.
                    860:         */
1.38      thorpej   861:        CCDGETBUF(cs, cbp);
1.24      thorpej   862:        cbp->cb_flags = 0;
1.6       cgd       863:        cbp->cb_buf.b_flags = bp->b_flags | B_CALL;
1.29      christos  864:        cbp->cb_buf.b_iodone = ccdiodone;
1.6       cgd       865:        cbp->cb_buf.b_proc = bp->b_proc;
1.11      thorpej   866:        cbp->cb_buf.b_dev = ci->ci_dev;         /* XXX */
1.6       cgd       867:        cbp->cb_buf.b_blkno = cbn + cboff;
                    868:        cbp->cb_buf.b_data = addr;
1.11      thorpej   869:        cbp->cb_buf.b_vp = ci->ci_vp;
1.1       hpeyerl   870:        if (cs->sc_ileave == 0)
1.6       cgd       871:                cbp->cb_buf.b_bcount = dbtob(ci->ci_size - cbn);
1.1       hpeyerl   872:        else
1.6       cgd       873:                cbp->cb_buf.b_bcount = dbtob(cs->sc_ileave - cboff);
                    874:        if (cbp->cb_buf.b_bcount > bcount)
                    875:                cbp->cb_buf.b_bcount = bcount;
                    876:
1.1       hpeyerl   877:        /*
1.6       cgd       878:         * context for ccdiodone
1.1       hpeyerl   879:         */
1.6       cgd       880:        cbp->cb_obp = bp;
1.36      thorpej   881:        cbp->cb_unit = cs->sc_unit;
                    882:        cbp->cb_comp = ccdisk;
1.6       cgd       883:
1.24      thorpej   884:        /* First buffer is dealt with. */
                    885:        cbpp[0] = cbp;
                    886:
1.1       hpeyerl   887: #ifdef DEBUG
1.3       hpeyerl   888:        if (ccddebug & CCDB_IO)
1.35      christos  889:                printf(" dev %x(u%d): cbp %p bn %d addr %p bcnt %ld\n",
1.34      christos  890:                    ci->ci_dev, ci-cs->sc_cinfo, cbp, cbp->cb_buf.b_blkno,
                    891:                    cbp->cb_buf.b_data, cbp->cb_buf.b_bcount);
1.1       hpeyerl   892: #endif
1.24      thorpej   893:
                    894:        /*
                    895:         * Mirrors have an additional write operation that is nearly
                    896:         * identical to the first.
                    897:         */
                    898:        if ((cs->sc_cflags & CCDF_MIRROR) &&
                    899:            ((cbp->cb_buf.b_flags & B_READ) == 0)) {
1.38      thorpej   900:                CCDGETBUF(cs, cbp);
1.24      thorpej   901:                *cbp = *cbpp[0];
                    902:                cbp->cb_flags = CBF_MIRROR;
                    903:                cbp->cb_buf.b_dev = ci2->ci_dev;        /* XXX */
                    904:                cbp->cb_buf.b_vp = ci2->ci_vp;
                    905:                cbp->cb_comp = ci2 - cs->sc_cinfo;
                    906:                cbpp[1] = cbp;
                    907:        }
1.1       hpeyerl   908: }
                    909:
1.11      thorpej   910: static void
1.3       hpeyerl   911: ccdintr(cs, bp)
                    912:        register struct ccd_softc *cs;
                    913:        register struct buf *bp;
1.1       hpeyerl   914: {
                    915:
                    916: #ifdef DEBUG
1.3       hpeyerl   917:        if (ccddebug & CCDB_FOLLOW)
1.35      christos  918:                printf("ccdintr(%p, %p)\n", cs, bp);
1.1       hpeyerl   919: #endif
                    920:        /*
                    921:         * Request is done for better or worse, wakeup the top half.
                    922:         */
                    923:        if (bp->b_flags & B_ERROR)
                    924:                bp->b_resid = bp->b_bcount;
1.23      thorpej   925:        disk_unbusy(&cs->sc_dkdev, (bp->b_bcount - bp->b_resid));
1.1       hpeyerl   926:        biodone(bp);
                    927: }
                    928:
                    929: /*
1.11      thorpej   930:  * Called at interrupt time.
1.1       hpeyerl   931:  * Mark the component as done and if all components are done,
                    932:  * take a ccd interrupt.
                    933:  */
1.3       hpeyerl   934: void
1.29      christos  935: ccdiodone(vbp)
                    936:        struct buf *vbp;
1.1       hpeyerl   937: {
1.29      christos  938:        struct ccdbuf *cbp = (struct ccdbuf *) vbp;
1.6       cgd       939:        register struct buf *bp = cbp->cb_obp;
                    940:        register int unit = cbp->cb_unit;
1.23      thorpej   941:        struct ccd_softc *cs = &ccd_softc[unit];
1.24      thorpej   942:        int count, cbflags, s;
                    943:        char *comptype;
1.1       hpeyerl   944:
                    945:        s = splbio();
                    946: #ifdef DEBUG
1.3       hpeyerl   947:        if (ccddebug & CCDB_FOLLOW)
1.35      christos  948:                printf("ccdiodone(%p)\n", cbp);
1.3       hpeyerl   949:        if (ccddebug & CCDB_IO) {
1.24      thorpej   950:                if (cbp->cb_flags & CBF_MIRROR)
1.35      christos  951:                        printf("ccdiodone: mirror component\n");
1.24      thorpej   952:                else
1.35      christos  953:                        printf("ccdiodone: bp %p bcount %ld resid %ld\n",
1.24      thorpej   954:                               bp, bp->b_bcount, bp->b_resid);
1.35      christos  955:                printf(" dev %x(u%d), cbp %p bn %d addr %p bcnt %ld\n",
1.6       cgd       956:                       cbp->cb_buf.b_dev, cbp->cb_comp, cbp,
                    957:                       cbp->cb_buf.b_blkno, cbp->cb_buf.b_data,
                    958:                       cbp->cb_buf.b_bcount);
1.1       hpeyerl   959:        }
                    960: #endif
                    961:
1.6       cgd       962:        if (cbp->cb_buf.b_flags & B_ERROR) {
1.24      thorpej   963:                if (cbp->cb_flags & CBF_MIRROR)
                    964:                        comptype = " (mirror)";
                    965:                else {
                    966:                        bp->b_flags |= B_ERROR;
                    967:                        bp->b_error = cbp->cb_buf.b_error ?
                    968:                            cbp->cb_buf.b_error : EIO;
                    969:                        comptype = "";
                    970:                }
                    971:
1.35      christos  972:                printf("%s: error %d on component %d%s\n",
1.24      thorpej   973:                       cs->sc_xname, bp->b_error, cbp->cb_comp, comptype);
1.1       hpeyerl   974:        }
1.6       cgd       975:        count = cbp->cb_buf.b_bcount;
1.24      thorpej   976:        cbflags = cbp->cb_flags;
1.38      thorpej   977:        CCDPUTBUF(cs, cbp);
1.1       hpeyerl   978:
                    979:        /*
                    980:         * If all done, "interrupt".
1.24      thorpej   981:         *
                    982:         * Note that mirror component buffers aren't counted against
                    983:         * the original I/O buffer.
                    984:         */
                    985:        if ((cbflags & CBF_MIRROR) == 0) {
                    986:                bp->b_resid -= count;
                    987:                if (bp->b_resid < 0)
                    988:                        panic("ccdiodone: count");
                    989:                if (bp->b_resid == 0)
                    990:                        ccdintr(&ccd_softc[unit], bp);
                    991:        }
1.1       hpeyerl   992:        splx(s);
                    993: }
                    994:
1.11      thorpej   995: /* ARGSUSED */
1.10      mycroft   996: int
1.11      thorpej   997: ccdread(dev, uio, flags)
1.3       hpeyerl   998:        dev_t dev;
                    999:        struct uio *uio;
1.11      thorpej  1000:        int flags;
1.3       hpeyerl  1001: {
1.11      thorpej  1002:        int unit = ccdunit(dev);
                   1003:        struct ccd_softc *cs;
1.3       hpeyerl  1004:
                   1005: #ifdef DEBUG
                   1006:        if (ccddebug & CCDB_FOLLOW)
1.35      christos 1007:                printf("ccdread(%x, %p)\n", dev, uio);
1.3       hpeyerl  1008: #endif
1.11      thorpej  1009:        if (unit >= numccd)
                   1010:                return (ENXIO);
                   1011:        cs = &ccd_softc[unit];
                   1012:
                   1013:        if ((cs->sc_flags & CCDF_INITED) == 0)
                   1014:                return (ENXIO);
                   1015:
                   1016:        /*
                   1017:         * XXX: It's not clear that using minphys() is completely safe,
                   1018:         * in particular, for raw I/O.  Underlying devices might have some
                   1019:         * non-obvious limits, because of the copy to user-space.
                   1020:         */
1.10      mycroft  1021:        return (physio(ccdstrategy, NULL, dev, B_READ, minphys, uio));
1.3       hpeyerl  1022: }
                   1023:
1.11      thorpej  1024: /* ARGSUSED */
1.10      mycroft  1025: int
1.11      thorpej  1026: ccdwrite(dev, uio, flags)
1.3       hpeyerl  1027:        dev_t dev;
                   1028:        struct uio *uio;
1.11      thorpej  1029:        int flags;
1.3       hpeyerl  1030: {
1.11      thorpej  1031:        int unit = ccdunit(dev);
                   1032:        struct ccd_softc *cs;
1.3       hpeyerl  1033:
                   1034: #ifdef DEBUG
                   1035:        if (ccddebug & CCDB_FOLLOW)
1.35      christos 1036:                printf("ccdwrite(%x, %p)\n", dev, uio);
1.3       hpeyerl  1037: #endif
1.11      thorpej  1038:        if (unit >= numccd)
                   1039:                return (ENXIO);
                   1040:        cs = &ccd_softc[unit];
                   1041:
                   1042:        if ((cs->sc_flags & CCDF_INITED) == 0)
                   1043:                return (ENXIO);
                   1044:
                   1045:        /*
                   1046:         * XXX: It's not clear that using minphys() is completely safe,
                   1047:         * in particular, for raw I/O.  Underlying devices might have some
                   1048:         * non-obvious limits, because of the copy to user-space.
                   1049:         */
1.10      mycroft  1050:        return (physio(ccdstrategy, NULL, dev, B_WRITE, minphys, uio));
1.3       hpeyerl  1051: }
                   1052:
1.11      thorpej  1053: int
                   1054: ccdioctl(dev, cmd, data, flag, p)
1.1       hpeyerl  1055:        dev_t dev;
1.5       cgd      1056:        u_long cmd;
1.1       hpeyerl  1057:        caddr_t data;
                   1058:        int flag;
1.11      thorpej  1059:        struct proc *p;
1.1       hpeyerl  1060: {
1.11      thorpej  1061:        int unit = ccdunit(dev);
                   1062:        int i, j, lookedup = 0, error = 0;
1.39      mycroft  1063:        int part, pmask;
1.11      thorpej  1064:        struct ccd_softc *cs;
                   1065:        struct ccd_ioctl *ccio = (struct ccd_ioctl *)data;
                   1066:        struct ccddevice ccd;
1.38      thorpej  1067:        struct ccdbuf *cbp;
1.11      thorpej  1068:        char **cpp;
                   1069:        struct vnode **vpp;
                   1070:
                   1071:        if (unit >= numccd)
                   1072:                return (ENXIO);
                   1073:        cs = &ccd_softc[unit];
                   1074:
                   1075:        bzero(&ccd, sizeof(ccd));
                   1076:
                   1077:        switch (cmd) {
                   1078:        case CCDIOCSET:
                   1079:                if (cs->sc_flags & CCDF_INITED)
                   1080:                        return (EBUSY);
                   1081:
                   1082:                if ((flag & FWRITE) == 0)
                   1083:                        return (EBADF);
                   1084:
1.29      christos 1085:                if ((error = ccdlock(cs)) != 0)
1.15      thorpej  1086:                        return (error);
                   1087:
1.11      thorpej  1088:                /* Fill in some important bits. */
                   1089:                ccd.ccd_unit = unit;
                   1090:                ccd.ccd_interleave = ccio->ccio_ileave;
                   1091:                ccd.ccd_flags = ccio->ccio_flags & CCDF_USERMASK;
                   1092:
                   1093:                /*
                   1094:                 * Allocate space for and copy in the array of
                   1095:                 * componet pathnames and device numbers.
                   1096:                 */
                   1097:                cpp = malloc(ccio->ccio_ndisks * sizeof(char *),
                   1098:                    M_DEVBUF, M_WAITOK);
                   1099:                vpp = malloc(ccio->ccio_ndisks * sizeof(struct vnode *),
                   1100:                    M_DEVBUF, M_WAITOK);
                   1101:
                   1102:                error = copyin((caddr_t)ccio->ccio_disks, (caddr_t)cpp,
                   1103:                    ccio->ccio_ndisks * sizeof(char **));
                   1104:                if (error) {
                   1105:                        free(vpp, M_DEVBUF);
                   1106:                        free(cpp, M_DEVBUF);
1.15      thorpej  1107:                        ccdunlock(cs);
1.11      thorpej  1108:                        return (error);
                   1109:                }
                   1110:
                   1111: #ifdef DEBUG
                   1112:                if (ccddebug & CCDB_INIT)
                   1113:                        for (i = 0; i < ccio->ccio_ndisks; ++i)
1.35      christos 1114:                                printf("ccdioctl: component %d: 0x%p\n",
1.11      thorpej  1115:                                    i, cpp[i]);
                   1116: #endif
                   1117:
                   1118:                for (i = 0; i < ccio->ccio_ndisks; ++i) {
                   1119: #ifdef DEBUG
                   1120:                        if (ccddebug & CCDB_INIT)
1.35      christos 1121:                                printf("ccdioctl: lookedup = %d\n", lookedup);
1.11      thorpej  1122: #endif
1.29      christos 1123:                        if ((error = ccdlookup(cpp[i], p, &vpp[i])) != 0) {
1.11      thorpej  1124:                                for (j = 0; j < lookedup; ++j)
1.12      thorpej  1125:                                        (void)vn_close(vpp[j], FREAD|FWRITE,
1.11      thorpej  1126:                                            p->p_ucred, p);
                   1127:                                free(vpp, M_DEVBUF);
                   1128:                                free(cpp, M_DEVBUF);
1.15      thorpej  1129:                                ccdunlock(cs);
1.11      thorpej  1130:                                return (error);
                   1131:                        }
                   1132:                        ++lookedup;
                   1133:                }
                   1134:                ccd.ccd_cpp = cpp;
                   1135:                ccd.ccd_vpp = vpp;
                   1136:                ccd.ccd_ndev = ccio->ccio_ndisks;
                   1137:
                   1138:                /*
                   1139:                 * Initialize the ccd.  Fills in the softc for us.
                   1140:                 */
1.29      christos 1141:                if ((error = ccdinit(&ccd, cpp, p)) != 0) {
1.11      thorpej  1142:                        for (j = 0; j < lookedup; ++j)
1.18      thorpej  1143:                                (void)vn_close(vpp[j], FREAD|FWRITE,
1.11      thorpej  1144:                                    p->p_ucred, p);
                   1145:                        bzero(&ccd_softc[unit], sizeof(struct ccd_softc));
                   1146:                        free(vpp, M_DEVBUF);
                   1147:                        free(cpp, M_DEVBUF);
1.15      thorpej  1148:                        ccdunlock(cs);
1.11      thorpej  1149:                        return (error);
                   1150:                }
                   1151:
                   1152:                /*
                   1153:                 * The ccd has been successfully initialized, so
1.23      thorpej  1154:                 * we can place it into the array.  Don't try to
                   1155:                 * read the disklabel until the disk has been attached,
                   1156:                 * because space for the disklabel is allocated
                   1157:                 * in disk_attach();
1.11      thorpej  1158:                 */
                   1159:                bcopy(&ccd, &ccddevs[unit], sizeof(ccd));
                   1160:                ccio->ccio_unit = unit;
                   1161:                ccio->ccio_size = cs->sc_size;
1.23      thorpej  1162:
                   1163:                /* Attach the disk. */
                   1164:                cs->sc_dkdev.dk_name = cs->sc_xname;
                   1165:                disk_attach(&cs->sc_dkdev);
                   1166:
                   1167:                /* Try and read the disklabel. */
1.11      thorpej  1168:                ccdgetdisklabel(dev);
                   1169:
1.15      thorpej  1170:                ccdunlock(cs);
                   1171:
1.11      thorpej  1172:                break;
                   1173:
                   1174:        case CCDIOCCLR:
                   1175:                if ((cs->sc_flags & CCDF_INITED) == 0)
                   1176:                        return (ENXIO);
                   1177:
                   1178:                if ((flag & FWRITE) == 0)
                   1179:                        return (EBADF);
                   1180:
1.29      christos 1181:                if ((error = ccdlock(cs)) != 0)
1.15      thorpej  1182:                        return (error);
                   1183:
1.11      thorpej  1184:                /*
                   1185:                 * Don't unconfigure if any other partitions are open
                   1186:                 * or if both the character and block flavors of this
                   1187:                 * partition are open.
                   1188:                 */
                   1189:                part = DISKPART(dev);
                   1190:                pmask = (1 << part);
                   1191:                if ((cs->sc_dkdev.dk_openmask & ~pmask) ||
                   1192:                    ((cs->sc_dkdev.dk_bopenmask & pmask) &&
1.15      thorpej  1193:                    (cs->sc_dkdev.dk_copenmask & pmask))) {
                   1194:                        ccdunlock(cs);
1.11      thorpej  1195:                        return (EBUSY);
1.15      thorpej  1196:                }
1.11      thorpej  1197:
                   1198:                /*
                   1199:                 * Free ccd_softc information and clear entry.
                   1200:                 */
1.22      thorpej  1201:
                   1202:                /* Close the components and free their pathnames. */
1.11      thorpej  1203:                for (i = 0; i < cs->sc_nccdisks; ++i) {
                   1204:                        /*
                   1205:                         * XXX: this close could potentially fail and
                   1206:                         * cause Bad Things.  Maybe we need to force
                   1207:                         * the close to happen?
                   1208:                         */
                   1209: #ifdef DEBUG
                   1210:                        if (ccddebug & CCDB_VNODE)
                   1211:                                vprint("CCDIOCCLR: vnode info",
                   1212:                                    cs->sc_cinfo[i].ci_vp);
                   1213: #endif
                   1214:                        (void)vn_close(cs->sc_cinfo[i].ci_vp, FREAD|FWRITE,
                   1215:                            p->p_ucred, p);
                   1216:                        free(cs->sc_cinfo[i].ci_path, M_DEVBUF);
1.38      thorpej  1217:                }
                   1218:
                   1219:                /* Free component buffer freelist. */
                   1220:                while ((cbp = cs->sc_freelist.lh_first) != NULL) {
                   1221:                        LIST_REMOVE(cbp, cb_list);
                   1222:                        FREE(cbp, M_DEVBUF);
1.22      thorpej  1223:                }
                   1224:
                   1225:                /* Free interleave index. */
                   1226:                for (i = 0; cs->sc_itable[i].ii_ndisk; ++i)
1.19      thorpej  1227:                        free(cs->sc_itable[i].ii_index, M_DEVBUF);
1.22      thorpej  1228:
                   1229:                /* Free component info and interleave table. */
1.11      thorpej  1230:                free(cs->sc_cinfo, M_DEVBUF);
                   1231:                free(cs->sc_itable, M_DEVBUF);
1.21      thorpej  1232:                cs->sc_flags &= ~CCDF_INITED;
1.11      thorpej  1233:
                   1234:                /*
                   1235:                 * Free ccddevice information and clear entry.
                   1236:                 */
                   1237:                free(ccddevs[unit].ccd_cpp, M_DEVBUF);
                   1238:                free(ccddevs[unit].ccd_vpp, M_DEVBUF);
                   1239:                bcopy(&ccd, &ccddevs[unit], sizeof(ccd));
1.15      thorpej  1240:
1.23      thorpej  1241:                /* Detatch the disk. */
1.26      hpeyerl  1242:                disk_detach(&cs->sc_dkdev);
1.23      thorpej  1243:
1.15      thorpej  1244:                ccdunlock(cs);
                   1245:
1.11      thorpej  1246:                break;
                   1247:
                   1248:        case DIOCGDINFO:
                   1249:                if ((cs->sc_flags & CCDF_INITED) == 0)
                   1250:                        return (ENXIO);
                   1251:
1.23      thorpej  1252:                *(struct disklabel *)data = *(cs->sc_dkdev.dk_label);
1.11      thorpej  1253:                break;
                   1254:
                   1255:        case DIOCGPART:
                   1256:                if ((cs->sc_flags & CCDF_INITED) == 0)
                   1257:                        return (ENXIO);
                   1258:
1.23      thorpej  1259:                ((struct partinfo *)data)->disklab = cs->sc_dkdev.dk_label;
1.11      thorpej  1260:                ((struct partinfo *)data)->part =
1.23      thorpej  1261:                    &cs->sc_dkdev.dk_label->d_partitions[DISKPART(dev)];
1.11      thorpej  1262:                break;
                   1263:
                   1264:        case DIOCWDINFO:
                   1265:        case DIOCSDINFO:
                   1266:                if ((cs->sc_flags & CCDF_INITED) == 0)
                   1267:                        return (ENXIO);
                   1268:
                   1269:                if ((flag & FWRITE) == 0)
                   1270:                        return (EBADF);
                   1271:
1.29      christos 1272:                if ((error = ccdlock(cs)) != 0)
1.15      thorpej  1273:                        return (error);
                   1274:
1.11      thorpej  1275:                cs->sc_flags |= CCDF_LABELLING;
                   1276:
1.23      thorpej  1277:                error = setdisklabel(cs->sc_dkdev.dk_label,
                   1278:                    (struct disklabel *)data, 0, cs->sc_dkdev.dk_cpulabel);
1.11      thorpej  1279:                if (error == 0) {
                   1280:                        if (cmd == DIOCWDINFO)
                   1281:                                error = writedisklabel(CCDLABELDEV(dev),
1.23      thorpej  1282:                                    ccdstrategy, cs->sc_dkdev.dk_label,
                   1283:                                    cs->sc_dkdev.dk_cpulabel);
1.11      thorpej  1284:                }
                   1285:
                   1286:                cs->sc_flags &= ~CCDF_LABELLING;
                   1287:
1.15      thorpej  1288:                ccdunlock(cs);
                   1289:
1.11      thorpej  1290:                if (error)
                   1291:                        return (error);
                   1292:                break;
                   1293:
                   1294:        case DIOCWLABEL:
                   1295:                if ((cs->sc_flags & CCDF_INITED) == 0)
                   1296:                        return (ENXIO);
                   1297:
                   1298:                if ((flag & FWRITE) == 0)
                   1299:                        return (EBADF);
                   1300:                if (*(int *)data != 0)
                   1301:                        cs->sc_flags |= CCDF_WLABEL;
                   1302:                else
                   1303:                        cs->sc_flags &= ~CCDF_WLABEL;
                   1304:                break;
                   1305:
                   1306:        default:
                   1307:                return (ENOTTY);
                   1308:        }
                   1309:
                   1310:        return (0);
1.1       hpeyerl  1311: }
                   1312:
1.11      thorpej  1313: int
1.1       hpeyerl  1314: ccdsize(dev)
                   1315:        dev_t dev;
                   1316: {
1.11      thorpej  1317:        struct ccd_softc *cs;
1.40    ! thorpej  1318:        struct disklabel *lp;
        !          1319:        int part, unit, omask, size;
        !          1320:
        !          1321:        unit = ccdunit(dev);
        !          1322:        if (unit >= numccd)
        !          1323:                return (-1);
        !          1324:        cs = &ccd_softc[unit];
1.11      thorpej  1325:
1.40    ! thorpej  1326:        if ((cs->sc_flags & CCDF_INITED) == 0)
1.11      thorpej  1327:                return (-1);
                   1328:
                   1329:        part = DISKPART(dev);
1.40    ! thorpej  1330:        omask = cs->sc_dkdev.dk_openmask & (1 << part);
        !          1331:        lp = cs->sc_dkdev.dk_label;
1.11      thorpej  1332:
1.40    ! thorpej  1333:        if (omask == 0 && ccdopen(dev, 0, S_IFBLK, curproc))
1.11      thorpej  1334:                return (-1);
                   1335:
1.40    ! thorpej  1336:        if (lp->d_partitions[part].p_fstype != FS_SWAP)
1.11      thorpej  1337:                size = -1;
                   1338:        else
1.40    ! thorpej  1339:                size = lp->d_partitions[part].p_size *
        !          1340:                    (lp->d_secsize / DEV_BSIZE);
1.11      thorpej  1341:
1.40    ! thorpej  1342:        if (omask == 0 && ccdclose(dev, 0, S_IFBLK, curproc))
1.11      thorpej  1343:                return (-1);
1.1       hpeyerl  1344:
1.11      thorpej  1345:        return (size);
1.1       hpeyerl  1346: }
                   1347:
1.9       cgd      1348: int
                   1349: ccddump(dev, blkno, va, size)
                   1350:        dev_t dev;
                   1351:        daddr_t blkno;
                   1352:        caddr_t va;
                   1353:        size_t size;
1.1       hpeyerl  1354: {
1.9       cgd      1355:
                   1356:        /* Not implemented. */
                   1357:        return ENXIO;
1.11      thorpej  1358: }
                   1359:
                   1360: /*
                   1361:  * Lookup the provided name in the filesystem.  If the file exists,
                   1362:  * is a valid block device, and isn't being used by anyone else,
                   1363:  * set *vpp to the file's vnode.
                   1364:  */
                   1365: static int
                   1366: ccdlookup(path, p, vpp)
                   1367:        char *path;
                   1368:        struct proc *p;
                   1369:        struct vnode **vpp;     /* result */
                   1370: {
                   1371:        struct nameidata nd;
                   1372:        struct vnode *vp;
                   1373:        struct vattr va;
                   1374:        int error;
                   1375:
                   1376:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, path, p);
1.29      christos 1377:        if ((error = vn_open(&nd, FREAD|FWRITE, 0)) != 0) {
1.11      thorpej  1378: #ifdef DEBUG
1.29      christos 1379:                if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))
1.35      christos 1380:                        printf("ccdlookup: vn_open error = %d\n", error);
1.11      thorpej  1381: #endif
                   1382:                return (error);
                   1383:        }
                   1384:        vp = nd.ni_vp;
                   1385:
                   1386:        if (vp->v_usecount > 1) {
                   1387:                VOP_UNLOCK(vp);
                   1388:                (void)vn_close(vp, FREAD|FWRITE, p->p_ucred, p);
                   1389:                return (EBUSY);
                   1390:        }
                   1391:
1.29      christos 1392:        if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)) != 0) {
1.11      thorpej  1393: #ifdef DEBUG
1.29      christos 1394:                if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))
1.35      christos 1395:                        printf("ccdlookup: getattr error = %d\n", error);
1.11      thorpej  1396: #endif
                   1397:                VOP_UNLOCK(vp);
                   1398:                (void)vn_close(vp, FREAD|FWRITE, p->p_ucred, p);
                   1399:                return (error);
                   1400:        }
                   1401:
                   1402:        /* XXX: eventually we should handle VREG, too. */
                   1403:        if (va.va_type != VBLK) {
                   1404:                VOP_UNLOCK(vp);
                   1405:                (void)vn_close(vp, FREAD|FWRITE, p->p_ucred, p);
                   1406:                return (ENOTBLK);
                   1407:        }
                   1408:
                   1409: #ifdef DEBUG
                   1410:        if (ccddebug & CCDB_VNODE)
                   1411:                vprint("ccdlookup: vnode info", vp);
                   1412: #endif
                   1413:
                   1414:        VOP_UNLOCK(vp);
                   1415:        *vpp = vp;
                   1416:        return (0);
                   1417: }
                   1418:
                   1419: /*
                   1420:  * Read the disklabel from the ccd.  If one is not present, fake one
                   1421:  * up.
                   1422:  */
                   1423: static void
                   1424: ccdgetdisklabel(dev)
                   1425:        dev_t dev;
                   1426: {
                   1427:        int unit = ccdunit(dev);
                   1428:        struct ccd_softc *cs = &ccd_softc[unit];
                   1429:        char *errstring;
1.23      thorpej  1430:        struct disklabel *lp = cs->sc_dkdev.dk_label;
                   1431:        struct cpu_disklabel *clp = cs->sc_dkdev.dk_cpulabel;
1.11      thorpej  1432:        struct ccdgeom *ccg = &cs->sc_geom;
                   1433:
                   1434:        bzero(lp, sizeof(*lp));
                   1435:        bzero(clp, sizeof(*clp));
                   1436:
                   1437:        lp->d_secperunit = cs->sc_size;
                   1438:        lp->d_secsize = ccg->ccg_secsize;
                   1439:        lp->d_nsectors = ccg->ccg_nsectors;
                   1440:        lp->d_ntracks = ccg->ccg_ntracks;
                   1441:        lp->d_ncylinders = ccg->ccg_ncylinders;
1.19      thorpej  1442:        lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
1.11      thorpej  1443:
                   1444:        strncpy(lp->d_typename, "ccd", sizeof(lp->d_typename));
                   1445:        lp->d_type = DTYPE_CCD;
                   1446:        strncpy(lp->d_packname, "fictitious", sizeof(lp->d_packname));
                   1447:        lp->d_rpm = 3600;
                   1448:        lp->d_interleave = 1;
                   1449:        lp->d_flags = 0;
                   1450:
                   1451:        lp->d_partitions[RAW_PART].p_offset = 0;
                   1452:        lp->d_partitions[RAW_PART].p_size = cs->sc_size;
                   1453:        lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED;
                   1454:        lp->d_npartitions = RAW_PART + 1;
                   1455:
                   1456:        lp->d_magic = DISKMAGIC;
                   1457:        lp->d_magic2 = DISKMAGIC;
1.23      thorpej  1458:        lp->d_checksum = dkcksum(cs->sc_dkdev.dk_label);
1.11      thorpej  1459:
                   1460:        /*
                   1461:         * Call the generic disklabel extraction routine.
                   1462:         */
1.29      christos 1463:        errstring = readdisklabel(CCDLABELDEV(dev), ccdstrategy,
                   1464:            cs->sc_dkdev.dk_label, cs->sc_dkdev.dk_cpulabel);
                   1465:        if (errstring)
1.11      thorpej  1466:                ccdmakedisklabel(cs);
                   1467:
                   1468: #ifdef DEBUG
                   1469:        /* It's actually extremely common to have unlabeled ccds. */
                   1470:        if (ccddebug & CCDB_LABEL)
                   1471:                if (errstring != NULL)
1.35      christos 1472:                        printf("%s: %s\n", cs->sc_xname, errstring);
1.11      thorpej  1473: #endif
                   1474: }
                   1475:
                   1476: /*
                   1477:  * Take care of things one might want to take care of in the event
                   1478:  * that a disklabel isn't present.
                   1479:  */
                   1480: static void
                   1481: ccdmakedisklabel(cs)
                   1482:        struct ccd_softc *cs;
                   1483: {
1.23      thorpej  1484:        struct disklabel *lp = cs->sc_dkdev.dk_label;
1.11      thorpej  1485:
                   1486:        /*
                   1487:         * For historical reasons, if there's no disklabel present
                   1488:         * the raw partition must be marked FS_BSDFFS.
                   1489:         */
                   1490:        lp->d_partitions[RAW_PART].p_fstype = FS_BSDFFS;
                   1491:
                   1492:        strncpy(lp->d_packname, "default label", sizeof(lp->d_packname));
1.15      thorpej  1493: }
                   1494:
                   1495: /*
                   1496:  * Wait interruptibly for an exclusive lock.
                   1497:  *
                   1498:  * XXX
                   1499:  * Several drivers do this; it should be abstracted and made MP-safe.
                   1500:  */
                   1501: static int
                   1502: ccdlock(cs)
                   1503:        struct ccd_softc *cs;
                   1504: {
                   1505:        int error;
                   1506:
                   1507:        while ((cs->sc_flags & CCDF_LOCKED) != 0) {
                   1508:                cs->sc_flags |= CCDF_WANTED;
                   1509:                if ((error = tsleep(cs, PRIBIO | PCATCH, "ccdlck", 0)) != 0)
                   1510:                        return (error);
                   1511:        }
                   1512:        cs->sc_flags |= CCDF_LOCKED;
                   1513:        return (0);
                   1514: }
                   1515:
                   1516: /*
                   1517:  * Unlock and wake up any waiters.
                   1518:  */
                   1519: static void
                   1520: ccdunlock(cs)
                   1521:        struct ccd_softc *cs;
                   1522: {
                   1523:
                   1524:        cs->sc_flags &= ~CCDF_LOCKED;
                   1525:        if ((cs->sc_flags & CCDF_WANTED) != 0) {
                   1526:                cs->sc_flags &= ~CCDF_WANTED;
                   1527:                wakeup(cs);
                   1528:        }
1.11      thorpej  1529: }
                   1530:
                   1531: #ifdef DEBUG
                   1532: static void
                   1533: printiinfo(ii)
                   1534:        struct ccdiinfo *ii;
                   1535: {
                   1536:        register int ix, i;
                   1537:
                   1538:        for (ix = 0; ii->ii_ndisk; ix++, ii++) {
1.35      christos 1539:                printf(" itab[%d]: #dk %d sblk %d soff %d",
1.34      christos 1540:                    ix, ii->ii_ndisk, ii->ii_startblk, ii->ii_startoff);
1.11      thorpej  1541:                for (i = 0; i < ii->ii_ndisk; i++)
1.35      christos 1542:                        printf(" %d", ii->ii_index[i]);
                   1543:                printf("\n");
1.11      thorpej  1544:        }
1.1       hpeyerl  1545: }
                   1546: #endif

CVSweb <webmaster@jp.NetBSD.org>