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

1.72.2.3! jdolecek    1: /*     $NetBSD: ccd.c,v 1.72.2.2 2002/01/10 19:52:45 thorpej Exp $     */
1.11      thorpej     2:
1.28      thorpej     3: /*-
1.59      thorpej     4:  * Copyright (c) 1996, 1997, 1998, 1999 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
1.45      jtc        29:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     30:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
1.28      thorpej    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.1       hpeyerl    90:  */
1.72.2.2  thorpej    91:
                     92: #include <sys/cdefs.h>
1.72.2.3! jdolecek   93: __KERNEL_RCSID(0, "$NetBSD: ccd.c,v 1.72.2.2 2002/01/10 19:52:45 thorpej Exp $");
1.1       hpeyerl    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.63      thorpej   101: #include <sys/pool.h>
1.11      thorpej   102: #include <sys/namei.h>
1.3       hpeyerl   103: #include <sys/stat.h>
                    104: #include <sys/ioctl.h>
                    105: #include <sys/disklabel.h>
1.11      thorpej   106: #include <sys/device.h>
                    107: #include <sys/disk.h>
                    108: #include <sys/syslog.h>
1.3       hpeyerl   109: #include <sys/fcntl.h>
1.11      thorpej   110: #include <sys/vnode.h>
1.31      christos  111: #include <sys/conf.h>
1.57      thorpej   112: #include <sys/lock.h>
1.56      thorpej   113: #include <sys/queue.h>
1.1       hpeyerl   114:
                    115: #include <dev/ccdvar.h>
                    116:
1.11      thorpej   117: #if defined(CCDDEBUG) && !defined(DEBUG)
                    118: #define DEBUG
                    119: #endif
                    120:
1.1       hpeyerl   121: #ifdef DEBUG
1.3       hpeyerl   122: #define CCDB_FOLLOW    0x01
                    123: #define CCDB_INIT      0x02
                    124: #define CCDB_IO                0x04
1.11      thorpej   125: #define CCDB_LABEL     0x08
                    126: #define CCDB_VNODE     0x10
1.24      thorpej   127: int ccddebug = 0x00;
1.1       hpeyerl   128: #endif
                    129:
1.6       cgd       130: #define        ccdunit(x)      DISKUNIT(x)
                    131:
                    132: struct ccdbuf {
                    133:        struct buf      cb_buf;         /* new I/O buf */
                    134:        struct buf      *cb_obp;        /* ptr. to original I/O buf */
1.59      thorpej   135:        struct ccd_softc *cb_sc;        /* pointer to ccd softc */
1.6       cgd       136:        int             cb_comp;        /* target component */
1.56      thorpej   137:        SIMPLEQ_ENTRY(ccdbuf) cb_q;     /* fifo of component buffers */
1.38      thorpej   138: };
1.24      thorpej   139:
1.63      thorpej   140: /* component buffer pool */
                    141: struct pool ccd_cbufpool;
                    142:
                    143: #define        CCD_GETBUF()            pool_get(&ccd_cbufpool, PR_NOWAIT)
                    144: #define        CCD_PUTBUF(cbp)         pool_put(&ccd_cbufpool, cbp)
1.1       hpeyerl   145:
1.11      thorpej   146: #define CCDLABELDEV(dev)       \
                    147:        (MAKEDISKDEV(major((dev)), ccdunit((dev)), RAW_PART))
1.1       hpeyerl   148:
1.11      thorpej   149: /* called by main() at boot time */
                    150: void   ccdattach __P((int));
                    151:
                    152: /* called by biodone() at interrupt time */
1.29      christos  153: void   ccdiodone __P((struct buf *));
                    154: int    ccdsize __P((dev_t));
1.11      thorpej   155:
                    156: static void ccdstart __P((struct ccd_softc *, struct buf *));
1.57      thorpej   157: static void ccdinterleave __P((struct ccd_softc *));
1.11      thorpej   158: static void ccdintr __P((struct ccd_softc *, struct buf *));
1.57      thorpej   159: static int ccdinit __P((struct ccd_softc *, char **, struct vnode **,
                    160:            struct proc *));
1.11      thorpej   161: static int ccdlookup __P((char *, struct proc *p, struct vnode **));
1.55      thorpej   162: static struct ccdbuf *ccdbuffer __P((struct ccd_softc *, struct buf *,
                    163:                daddr_t, caddr_t, long));
1.44      thorpej   164: static void ccdgetdefaultlabel __P((struct ccd_softc *, struct disklabel *));
1.11      thorpej   165: static void ccdgetdisklabel __P((dev_t));
                    166: static void ccdmakedisklabel __P((struct ccd_softc *));
1.3       hpeyerl   167:
1.11      thorpej   168: #ifdef DEBUG
                    169: static void printiinfo __P((struct ccdiinfo *));
                    170: #endif
                    171:
                    172: /* Non-private for the benefit of libkvm. */
                    173: struct ccd_softc *ccd_softc;
                    174: int    numccd = 0;
1.1       hpeyerl   175:
1.3       hpeyerl   176: /*
1.11      thorpej   177:  * Called by main() during pseudo-device attachment.  All we need
                    178:  * to do is allocate enough space for devices to be configured later.
1.1       hpeyerl   179:  */
                    180: void
1.3       hpeyerl   181: ccdattach(num)
                    182:        int num;
                    183: {
1.57      thorpej   184:        struct ccd_softc *cs;
                    185:        int i;
                    186:
1.11      thorpej   187:        if (num <= 0) {
                    188: #ifdef DIAGNOSTIC
                    189:                panic("ccdattach: count <= 0");
                    190: #endif
1.3       hpeyerl   191:                return;
1.11      thorpej   192:        }
                    193:
                    194:        ccd_softc = (struct ccd_softc *)malloc(num * sizeof(struct ccd_softc),
1.72.2.3! jdolecek  195:            M_DEVBUF, M_NOWAIT|M_ZERO);
1.57      thorpej   196:        if (ccd_softc == NULL) {
1.35      christos  197:                printf("WARNING: no memory for concatenated disks\n");
1.3       hpeyerl   198:                return;
                    199:        }
                    200:        numccd = num;
1.57      thorpej   201:
1.63      thorpej   202:        /* Initialize the component buffer pool. */
                    203:        pool_init(&ccd_cbufpool, sizeof(struct ccdbuf), 0,
                    204:            0, 0, "ccdpl", 0, NULL, NULL, M_DEVBUF);
                    205:
1.57      thorpej   206:        /* Initialize per-softc structures. */
                    207:        for (i = 0; i < num; i++) {
                    208:                cs = &ccd_softc[i];
                    209:                sprintf(cs->sc_xname, "ccd%d", i);      /* XXX */
                    210:                cs->sc_dkdev.dk_name = cs->sc_xname;    /* XXX */
                    211:                lockinit(&cs->sc_lock, PRIBIO, "ccdlk", 0, 0);
                    212:        }
1.1       hpeyerl   213: }
                    214:
1.11      thorpej   215: static int
1.57      thorpej   216: ccdinit(cs, cpaths, vpp, p)
                    217:        struct ccd_softc *cs;
1.11      thorpej   218:        char **cpaths;
1.57      thorpej   219:        struct vnode **vpp;
1.11      thorpej   220:        struct proc *p;
1.1       hpeyerl   221: {
1.68      augustss  222:        struct ccdcinfo *ci = NULL;
                    223:        size_t size;
                    224:        int ix;
1.11      thorpej   225:        struct vattr va;
1.1       hpeyerl   226:        size_t minsize;
1.11      thorpej   227:        int maxsecsize;
1.7       cgd       228:        struct partinfo dpart;
1.11      thorpej   229:        struct ccdgeom *ccg = &cs->sc_geom;
                    230:        char tmppath[MAXPATHLEN];
1.67      enami     231:        int error, path_alloced;
1.1       hpeyerl   232:
                    233: #ifdef DEBUG
1.3       hpeyerl   234:        if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))
1.59      thorpej   235:                printf("%s: ccdinit\n", cs->sc_xname);
1.1       hpeyerl   236: #endif
1.11      thorpej   237:
                    238:        /* Allocate space for the component info. */
                    239:        cs->sc_cinfo = malloc(cs->sc_nccdisks * sizeof(struct ccdcinfo),
                    240:            M_DEVBUF, M_WAITOK);
                    241:
1.57      thorpej   242:        cs->sc_size = 0;
                    243:
1.1       hpeyerl   244:        /*
                    245:         * Verify that each component piece exists and record
                    246:         * relevant information about it.
                    247:         */
1.11      thorpej   248:        maxsecsize = 0;
1.1       hpeyerl   249:        minsize = 0;
1.67      enami     250:        for (ix = 0, path_alloced = 0; ix < cs->sc_nccdisks; ix++) {
1.1       hpeyerl   251:                ci = &cs->sc_cinfo[ix];
1.57      thorpej   252:                ci->ci_vp = vpp[ix];
1.11      thorpej   253:
                    254:                /*
                    255:                 * Copy in the pathname of the component.
                    256:                 */
1.72      thorpej   257:                memset(tmppath, 0, sizeof(tmppath));    /* sanity */
1.29      christos  258:                error = copyinstr(cpaths[ix], tmppath,
                    259:                    MAXPATHLEN, &ci->ci_pathlen);
                    260:                if (error) {
1.11      thorpej   261: #ifdef DEBUG
                    262:                        if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))
1.35      christos  263:                                printf("%s: can't copy path, error = %d\n",
1.23      thorpej   264:                                    cs->sc_xname, error);
1.11      thorpej   265: #endif
1.67      enami     266:                        goto out;
1.11      thorpej   267:                }
                    268:                ci->ci_path = malloc(ci->ci_pathlen, M_DEVBUF, M_WAITOK);
1.72      thorpej   269:                memcpy(ci->ci_path, tmppath, ci->ci_pathlen);
1.67      enami     270:                path_alloced++;
1.11      thorpej   271:
                    272:                /*
                    273:                 * XXX: Cache the component's dev_t.
                    274:                 */
1.57      thorpej   275:                if ((error = VOP_GETATTR(vpp[ix], &va, p->p_ucred, p)) != 0) {
1.11      thorpej   276: #ifdef DEBUG
                    277:                        if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))
1.35      christos  278:                                printf("%s: %s: getattr failed %s = %d\n",
1.23      thorpej   279:                                    cs->sc_xname, ci->ci_path,
1.11      thorpej   280:                                    "error", error);
                    281: #endif
1.67      enami     282:                        goto out;
1.11      thorpej   283:                }
                    284:                ci->ci_dev = va.va_rdev;
                    285:
1.3       hpeyerl   286:                /*
1.11      thorpej   287:                 * Get partition information for the component.
1.3       hpeyerl   288:                 */
1.57      thorpej   289:                error = VOP_IOCTL(vpp[ix], DIOCGPART, (caddr_t)&dpart,
1.29      christos  290:                    FREAD, p->p_ucred, p);
                    291:                if (error) {
1.11      thorpej   292: #ifdef DEBUG
                    293:                        if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))
1.35      christos  294:                                 printf("%s: %s: ioctl failed, error = %d\n",
1.23      thorpej   295:                                     cs->sc_xname, ci->ci_path, error);
1.11      thorpej   296: #endif
1.67      enami     297:                        goto out;
1.11      thorpej   298:                }
1.69      enami     299:
                    300: /*
                    301:  * This diagnostic test is disabled (for now?) since not all port supports
                    302:  * on-disk BSD disklabel.
                    303:  */
                    304: #if 0 /* def DIAGNOSTIC */
                    305:                /* Check fstype field of component. */
                    306:                if (dpart.part->p_fstype != FS_CCD)
                    307:                        printf("%s: WARNING: %s: fstype %d != FS_CCD\n",
                    308:                            cs->sc_xname, ci->ci_path, dpart.part->p_fstype);
                    309: #endif
1.7       cgd       310:
1.11      thorpej   311:                /*
                    312:                 * Calculate the size, truncating to an interleave
                    313:                 * boundary if necessary.
                    314:                 */
1.46      thorpej   315:                maxsecsize =
                    316:                    ((dpart.disklab->d_secsize > maxsecsize) ?
                    317:                    dpart.disklab->d_secsize : maxsecsize);
                    318:                size = dpart.part->p_size;
1.1       hpeyerl   319:                if (cs->sc_ileave > 1)
                    320:                        size -= size % cs->sc_ileave;
1.11      thorpej   321:
1.1       hpeyerl   322:                if (size == 0) {
1.11      thorpej   323: #ifdef DEBUG
                    324:                        if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))
1.35      christos  325:                                printf("%s: %s: size == 0\n",
1.23      thorpej   326:                                    cs->sc_xname, ci->ci_path);
1.11      thorpej   327: #endif
1.67      enami     328:                        error = ENODEV;
                    329:                        goto out;
1.3       hpeyerl   330:                }
1.11      thorpej   331:
1.1       hpeyerl   332:                if (minsize == 0 || size < minsize)
                    333:                        minsize = size;
                    334:                ci->ci_size = size;
                    335:                cs->sc_size += size;
                    336:        }
1.11      thorpej   337:
                    338:        /*
                    339:         * Don't allow the interleave to be smaller than
                    340:         * the biggest component sector.
                    341:         */
                    342:        if ((cs->sc_ileave > 0) &&
                    343:            (cs->sc_ileave < (maxsecsize / DEV_BSIZE))) {
                    344: #ifdef DEBUG
                    345:                if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))
1.35      christos  346:                        printf("%s: interleave must be at least %d\n",
1.23      thorpej   347:                            cs->sc_xname, (maxsecsize / DEV_BSIZE));
1.11      thorpej   348: #endif
1.67      enami     349:                error = EINVAL;
                    350:                goto out;
1.11      thorpej   351:        }
                    352:
1.1       hpeyerl   353:        /*
                    354:         * If uniform interleave is desired set all sizes to that of
                    355:         * the smallest component.
                    356:         */
1.57      thorpej   357:        if (cs->sc_flags & CCDF_UNIFORM) {
1.1       hpeyerl   358:                for (ci = cs->sc_cinfo;
                    359:                     ci < &cs->sc_cinfo[cs->sc_nccdisks]; ci++)
                    360:                        ci->ci_size = minsize;
1.24      thorpej   361:
1.53      thorpej   362:                cs->sc_size = cs->sc_nccdisks * minsize;
1.1       hpeyerl   363:        }
1.11      thorpej   364:
                    365:        /*
                    366:         * Construct the interleave table.
                    367:         */
1.57      thorpej   368:        ccdinterleave(cs);
1.11      thorpej   369:
1.1       hpeyerl   370:        /*
1.11      thorpej   371:         * Create pseudo-geometry based on 1MB cylinders.  It's
                    372:         * pretty close.
1.1       hpeyerl   373:         */
1.11      thorpej   374:        ccg->ccg_secsize = DEV_BSIZE;
1.19      thorpej   375:        ccg->ccg_ntracks = 1;
1.11      thorpej   376:        ccg->ccg_nsectors = 1024 * (1024 / ccg->ccg_secsize);
                    377:        ccg->ccg_ncylinders = cs->sc_size / ccg->ccg_nsectors;
                    378:
                    379:        cs->sc_flags |= CCDF_INITED;
1.23      thorpej   380:
1.11      thorpej   381:        return (0);
1.67      enami     382:
                    383:  out:
                    384:        for (ix = 0; ix < path_alloced; ix++)
                    385:                free(cs->sc_cinfo[ix].ci_path, M_DEVBUF);
                    386:        free(cs->sc_cinfo, M_DEVBUF);
                    387:        return (error);
1.1       hpeyerl   388: }
                    389:
1.11      thorpej   390: static void
1.57      thorpej   391: ccdinterleave(cs)
1.68      augustss  392:        struct ccd_softc *cs;
1.1       hpeyerl   393: {
1.68      augustss  394:        struct ccdcinfo *ci, *smallci;
                    395:        struct ccdiinfo *ii;
                    396:        daddr_t bn, lbn;
                    397:        int ix;
1.1       hpeyerl   398:        u_long size;
                    399:
                    400: #ifdef DEBUG
1.3       hpeyerl   401:        if (ccddebug & CCDB_INIT)
1.35      christos  402:                printf("ccdinterleave(%p): ileave %d\n", cs, cs->sc_ileave);
1.1       hpeyerl   403: #endif
                    404:        /*
                    405:         * Allocate an interleave table.
                    406:         * Chances are this is too big, but we don't care.
                    407:         */
                    408:        size = (cs->sc_nccdisks + 1) * sizeof(struct ccdiinfo);
1.72.2.3! jdolecek  409:        cs->sc_itable = (struct ccdiinfo *)malloc(size, M_DEVBUF,
        !           410:            M_WAITOK|M_ZERO);
1.11      thorpej   411:
1.1       hpeyerl   412:        /*
                    413:         * Trivial case: no interleave (actually interleave of disk size).
1.11      thorpej   414:         * Each table entry represents a single component in its entirety.
1.1       hpeyerl   415:         */
                    416:        if (cs->sc_ileave == 0) {
                    417:                bn = 0;
                    418:                ii = cs->sc_itable;
1.11      thorpej   419:
1.1       hpeyerl   420:                for (ix = 0; ix < cs->sc_nccdisks; ix++) {
1.19      thorpej   421:                        /* Allocate space for ii_index. */
                    422:                        ii->ii_index = malloc(sizeof(int), M_DEVBUF, M_WAITOK);
1.1       hpeyerl   423:                        ii->ii_ndisk = 1;
                    424:                        ii->ii_startblk = bn;
                    425:                        ii->ii_startoff = 0;
                    426:                        ii->ii_index[0] = ix;
                    427:                        bn += cs->sc_cinfo[ix].ci_size;
                    428:                        ii++;
                    429:                }
                    430:                ii->ii_ndisk = 0;
                    431: #ifdef DEBUG
1.3       hpeyerl   432:                if (ccddebug & CCDB_INIT)
1.1       hpeyerl   433:                        printiinfo(cs->sc_itable);
                    434: #endif
1.11      thorpej   435:                return;
1.1       hpeyerl   436:        }
1.11      thorpej   437:
1.1       hpeyerl   438:        /*
                    439:         * The following isn't fast or pretty; it doesn't have to be.
                    440:         */
                    441:        size = 0;
                    442:        bn = lbn = 0;
                    443:        for (ii = cs->sc_itable; ; ii++) {
1.11      thorpej   444:                /* Allocate space for ii_index. */
1.19      thorpej   445:                ii->ii_index = malloc((sizeof(int) * cs->sc_nccdisks),
                    446:                    M_DEVBUF, M_WAITOK);
1.11      thorpej   447:
1.1       hpeyerl   448:                /*
                    449:                 * Locate the smallest of the remaining components
                    450:                 */
                    451:                smallci = NULL;
                    452:                for (ci = cs->sc_cinfo;
                    453:                     ci < &cs->sc_cinfo[cs->sc_nccdisks]; ci++)
                    454:                        if (ci->ci_size > size &&
                    455:                            (smallci == NULL ||
                    456:                             ci->ci_size < smallci->ci_size))
                    457:                                smallci = ci;
1.11      thorpej   458:
1.1       hpeyerl   459:                /*
                    460:                 * Nobody left, all done
                    461:                 */
                    462:                if (smallci == NULL) {
                    463:                        ii->ii_ndisk = 0;
                    464:                        break;
                    465:                }
1.11      thorpej   466:
1.1       hpeyerl   467:                /*
                    468:                 * Record starting logical block and component offset
                    469:                 */
                    470:                ii->ii_startblk = bn / cs->sc_ileave;
                    471:                ii->ii_startoff = lbn;
1.11      thorpej   472:
1.1       hpeyerl   473:                /*
                    474:                 * Determine how many disks take part in this interleave
                    475:                 * and record their indices.
                    476:                 */
                    477:                ix = 0;
                    478:                for (ci = cs->sc_cinfo;
                    479:                     ci < &cs->sc_cinfo[cs->sc_nccdisks]; ci++)
                    480:                        if (ci->ci_size >= smallci->ci_size)
                    481:                                ii->ii_index[ix++] = ci - cs->sc_cinfo;
                    482:                ii->ii_ndisk = ix;
                    483:                bn += ix * (smallci->ci_size - size);
                    484:                lbn = smallci->ci_size / cs->sc_ileave;
                    485:                size = smallci->ci_size;
                    486:        }
                    487: #ifdef DEBUG
1.3       hpeyerl   488:        if (ccddebug & CCDB_INIT)
1.1       hpeyerl   489:                printiinfo(cs->sc_itable);
                    490: #endif
                    491: }
                    492:
1.11      thorpej   493: /* ARGSUSED */
                    494: int
                    495: ccdopen(dev, flags, fmt, p)
1.1       hpeyerl   496:        dev_t dev;
1.11      thorpej   497:        int flags, fmt;
                    498:        struct proc *p;
1.1       hpeyerl   499: {
                    500:        int unit = ccdunit(dev);
1.11      thorpej   501:        struct ccd_softc *cs;
                    502:        struct disklabel *lp;
1.15      thorpej   503:        int error = 0, part, pmask;
1.1       hpeyerl   504:
                    505: #ifdef DEBUG
1.3       hpeyerl   506:        if (ccddebug & CCDB_FOLLOW)
1.43      fair      507:                printf("ccdopen(0x%x, 0x%x)\n", dev, flags);
1.1       hpeyerl   508: #endif
1.11      thorpej   509:        if (unit >= numccd)
                    510:                return (ENXIO);
                    511:        cs = &ccd_softc[unit];
1.15      thorpej   512:
1.57      thorpej   513:        if ((error = lockmgr(&cs->sc_lock, LK_EXCLUSIVE, NULL)) != 0)
1.15      thorpej   514:                return (error);
                    515:
1.23      thorpej   516:        lp = cs->sc_dkdev.dk_label;
1.11      thorpej   517:
                    518:        part = DISKPART(dev);
                    519:        pmask = (1 << part);
                    520:
1.15      thorpej   521:        /*
                    522:         * If we're initialized, check to see if there are any other
                    523:         * open partitions.  If not, then it's safe to update
                    524:         * the in-core disklabel.
                    525:         */
                    526:        if ((cs->sc_flags & CCDF_INITED) && (cs->sc_dkdev.dk_openmask == 0))
                    527:                ccdgetdisklabel(dev);
                    528:
1.11      thorpej   529:        /* Check that the partition exists. */
1.27      thorpej   530:        if (part != RAW_PART) {
                    531:                if (((cs->sc_flags & CCDF_INITED) == 0) ||
1.37      thorpej   532:                    ((part >= lp->d_npartitions) ||
1.27      thorpej   533:                     (lp->d_partitions[part].p_fstype == FS_UNUSED))) {
                    534:                        error = ENXIO;
                    535:                        goto done;
                    536:                }
1.15      thorpej   537:        }
1.11      thorpej   538:
                    539:        /* Prevent our unit from being unconfigured while open. */
                    540:        switch (fmt) {
                    541:        case S_IFCHR:
                    542:                cs->sc_dkdev.dk_copenmask |= pmask;
                    543:                break;
                    544:
                    545:        case S_IFBLK:
                    546:                cs->sc_dkdev.dk_bopenmask |= pmask;
                    547:                break;
                    548:        }
                    549:        cs->sc_dkdev.dk_openmask =
                    550:            cs->sc_dkdev.dk_copenmask | cs->sc_dkdev.dk_bopenmask;
                    551:
1.15      thorpej   552:  done:
1.57      thorpej   553:        (void) lockmgr(&cs->sc_lock, LK_RELEASE, NULL);
1.33      thorpej   554:        return (error);
1.7       cgd       555: }
                    556:
1.11      thorpej   557: /* ARGSUSED */
                    558: int
                    559: ccdclose(dev, flags, fmt, p)
1.7       cgd       560:        dev_t dev;
1.11      thorpej   561:        int flags, fmt;
                    562:        struct proc *p;
1.7       cgd       563: {
1.11      thorpej   564:        int unit = ccdunit(dev);
                    565:        struct ccd_softc *cs;
1.15      thorpej   566:        int error = 0, part;
1.11      thorpej   567:
1.7       cgd       568: #ifdef DEBUG
                    569:        if (ccddebug & CCDB_FOLLOW)
1.43      fair      570:                printf("ccdclose(0x%x, 0x%x)\n", dev, flags);
1.7       cgd       571: #endif
1.11      thorpej   572:
                    573:        if (unit >= numccd)
                    574:                return (ENXIO);
                    575:        cs = &ccd_softc[unit];
1.15      thorpej   576:
1.57      thorpej   577:        if ((error = lockmgr(&cs->sc_lock, LK_EXCLUSIVE, NULL)) != 0)
1.15      thorpej   578:                return (error);
                    579:
1.11      thorpej   580:        part = DISKPART(dev);
                    581:
                    582:        /* ...that much closer to allowing unconfiguration... */
                    583:        switch (fmt) {
                    584:        case S_IFCHR:
                    585:                cs->sc_dkdev.dk_copenmask &= ~(1 << part);
                    586:                break;
                    587:
                    588:        case S_IFBLK:
                    589:                cs->sc_dkdev.dk_bopenmask &= ~(1 << part);
                    590:                break;
                    591:        }
                    592:        cs->sc_dkdev.dk_openmask =
                    593:            cs->sc_dkdev.dk_copenmask | cs->sc_dkdev.dk_bopenmask;
                    594:
1.57      thorpej   595:        (void) lockmgr(&cs->sc_lock, LK_RELEASE, NULL);
1.7       cgd       596:        return (0);
1.1       hpeyerl   597: }
                    598:
1.11      thorpej   599: void
1.1       hpeyerl   600: ccdstrategy(bp)
1.68      augustss  601:        struct buf *bp;
1.1       hpeyerl   602: {
1.68      augustss  603:        int unit = ccdunit(bp->b_dev);
                    604:        struct ccd_softc *cs = &ccd_softc[unit];
                    605:        int s;
1.11      thorpej   606:        int wlabel;
1.15      thorpej   607:        struct disklabel *lp;
1.1       hpeyerl   608:
                    609: #ifdef DEBUG
1.3       hpeyerl   610:        if (ccddebug & CCDB_FOLLOW)
1.35      christos  611:                printf("ccdstrategy(%p): unit %d\n", bp, unit);
1.1       hpeyerl   612: #endif
1.3       hpeyerl   613:        if ((cs->sc_flags & CCDF_INITED) == 0) {
1.59      thorpej   614: #ifdef DEBUG
                    615:                if (ccddebug & CCDB_FOLLOW)
                    616:                        printf("ccdstrategy: unit %d: not inited\n", unit);
                    617: #endif
1.1       hpeyerl   618:                bp->b_error = ENXIO;
                    619:                bp->b_flags |= B_ERROR;
                    620:                goto done;
                    621:        }
1.11      thorpej   622:
                    623:        /* If it's a nil transfer, wake up the top half now. */
                    624:        if (bp->b_bcount == 0)
                    625:                goto done;
                    626:
1.23      thorpej   627:        lp = cs->sc_dkdev.dk_label;
1.15      thorpej   628:
1.11      thorpej   629:        /*
1.17      thorpej   630:         * Do bounds checking and adjust transfer.  If there's an
1.11      thorpej   631:         * error, the bounds check will flag that for us.
                    632:         */
                    633:        wlabel = cs->sc_flags & (CCDF_WLABEL|CCDF_LABELLING);
1.16      thorpej   634:        if (DISKPART(bp->b_dev) != RAW_PART)
1.15      thorpej   635:                if (bounds_check_with_label(bp, lp, wlabel) <= 0)
1.1       hpeyerl   636:                        goto done;
1.11      thorpej   637:
1.1       hpeyerl   638:        bp->b_resid = bp->b_bcount;
1.11      thorpej   639:
1.1       hpeyerl   640:        /*
                    641:         * "Start" the unit.
                    642:         */
                    643:        s = splbio();
1.3       hpeyerl   644:        ccdstart(cs, bp);
1.1       hpeyerl   645:        splx(s);
                    646:        return;
                    647: done:
                    648:        biodone(bp);
                    649: }
                    650:
1.11      thorpej   651: static void
1.3       hpeyerl   652: ccdstart(cs, bp)
1.68      augustss  653:        struct ccd_softc *cs;
                    654:        struct buf *bp;
1.1       hpeyerl   655: {
1.68      augustss  656:        long bcount, rcount;
1.55      thorpej   657:        struct ccdbuf *cbp;
1.1       hpeyerl   658:        caddr_t addr;
                    659:        daddr_t bn;
1.20      thorpej   660:        struct partition *pp;
1.56      thorpej   661:        SIMPLEQ_HEAD(, ccdbuf) cbufq;
1.1       hpeyerl   662:
                    663: #ifdef DEBUG
1.3       hpeyerl   664:        if (ccddebug & CCDB_FOLLOW)
1.35      christos  665:                printf("ccdstart(%p, %p)\n", cs, bp);
1.1       hpeyerl   666: #endif
1.11      thorpej   667:
1.23      thorpej   668:        /* Instrumentation. */
                    669:        disk_busy(&cs->sc_dkdev);
1.11      thorpej   670:
1.1       hpeyerl   671:        /*
1.17      thorpej   672:         * Translate the partition-relative block number to an absolute.
1.1       hpeyerl   673:         */
1.20      thorpej   674:        bn = bp->b_blkno;
                    675:        if (DISKPART(bp->b_dev) != RAW_PART) {
1.23      thorpej   676:                pp = &cs->sc_dkdev.dk_label->d_partitions[DISKPART(bp->b_dev)];
1.20      thorpej   677:                bn += pp->p_offset;
                    678:        }
1.17      thorpej   679:
                    680:        /*
1.56      thorpej   681:         * Allocate the component buffers.
1.17      thorpej   682:         */
1.56      thorpej   683:        SIMPLEQ_INIT(&cbufq);
1.3       hpeyerl   684:        addr = bp->b_data;
1.1       hpeyerl   685:        for (bcount = bp->b_bcount; bcount > 0; bcount -= rcount) {
1.55      thorpej   686:                cbp = ccdbuffer(cs, bp, bn, addr, bcount);
1.56      thorpej   687:                if (cbp == NULL) {
                    688:                        /* Free the already allocated component buffers. */
                    689:                        while ((cbp = SIMPLEQ_FIRST(&cbufq)) != NULL) {
                    690:                                SIMPLEQ_REMOVE_HEAD(&cbufq, cbp, cb_q);
1.63      thorpej   691:                                CCD_PUTBUF(cbp);
1.56      thorpej   692:                        }
                    693:
                    694:                        /* Notify the upper layer we are out of memory. */
                    695:                        bp->b_error = ENOMEM;
                    696:                        bp->b_flags |= B_ERROR;
1.64      chs       697:                        biodone(bp);
1.59      thorpej   698:                        disk_unbusy(&cs->sc_dkdev, 0);
1.56      thorpej   699:                        return;
                    700:                }
                    701:                SIMPLEQ_INSERT_TAIL(&cbufq, cbp, cb_q);
1.55      thorpej   702:                rcount = cbp->cb_buf.b_bcount;
1.56      thorpej   703:                bn += btodb(rcount);
                    704:                addr += rcount;
                    705:        }
                    706:
                    707:        /* Now fire off the requests. */
                    708:        while ((cbp = SIMPLEQ_FIRST(&cbufq)) != NULL) {
                    709:                SIMPLEQ_REMOVE_HEAD(&cbufq, cbp, cb_q);
1.55      thorpej   710:                if ((cbp->cb_buf.b_flags & B_READ) == 0)
                    711:                        cbp->cb_buf.b_vp->v_numoutput++;
                    712:                VOP_STRATEGY(&cbp->cb_buf);
1.1       hpeyerl   713:        }
                    714: }
                    715:
                    716: /*
                    717:  * Build a component buffer header.
                    718:  */
1.55      thorpej   719: static struct ccdbuf *
                    720: ccdbuffer(cs, bp, bn, addr, bcount)
1.68      augustss  721:        struct ccd_softc *cs;
1.1       hpeyerl   722:        struct buf *bp;
                    723:        daddr_t bn;
                    724:        caddr_t addr;
                    725:        long bcount;
                    726: {
1.68      augustss  727:        struct ccdcinfo *ci;
                    728:        struct ccdbuf *cbp;
                    729:        daddr_t cbn, cboff;
                    730:        u_int64_t cbc;
1.36      thorpej   731:        int ccdisk;
1.1       hpeyerl   732:
                    733: #ifdef DEBUG
1.3       hpeyerl   734:        if (ccddebug & CCDB_IO)
1.35      christos  735:                printf("ccdbuffer(%p, %p, %d, %p, %ld)\n",
1.1       hpeyerl   736:                       cs, bp, bn, addr, bcount);
                    737: #endif
                    738:        /*
                    739:         * Determine which component bn falls in.
                    740:         */
                    741:        cbn = bn;
                    742:        cboff = 0;
1.11      thorpej   743:
1.1       hpeyerl   744:        /*
                    745:         * Serially concatenated
                    746:         */
                    747:        if (cs->sc_ileave == 0) {
1.68      augustss  748:                daddr_t sblk;
1.1       hpeyerl   749:
                    750:                sblk = 0;
1.36      thorpej   751:                for (ccdisk = 0, ci = &cs->sc_cinfo[ccdisk];
                    752:                    cbn >= sblk + ci->ci_size;
                    753:                    ccdisk++, ci = &cs->sc_cinfo[ccdisk])
1.1       hpeyerl   754:                        sblk += ci->ci_size;
                    755:                cbn -= sblk;
                    756:        }
                    757:        /*
                    758:         * Interleaved
                    759:         */
                    760:        else {
1.68      augustss  761:                struct ccdiinfo *ii;
1.36      thorpej   762:                int off;
1.1       hpeyerl   763:
                    764:                cboff = cbn % cs->sc_ileave;
                    765:                cbn /= cs->sc_ileave;
                    766:                for (ii = cs->sc_itable; ii->ii_ndisk; ii++)
                    767:                        if (ii->ii_startblk > cbn)
                    768:                                break;
                    769:                ii--;
                    770:                off = cbn - ii->ii_startblk;
                    771:                if (ii->ii_ndisk == 1) {
                    772:                        ccdisk = ii->ii_index[0];
                    773:                        cbn = ii->ii_startoff + off;
                    774:                } else {
1.53      thorpej   775:                        ccdisk = ii->ii_index[off % ii->ii_ndisk];
                    776:                        cbn = ii->ii_startoff + off / ii->ii_ndisk;
1.1       hpeyerl   777:                }
                    778:                cbn *= cs->sc_ileave;
                    779:                ci = &cs->sc_cinfo[ccdisk];
                    780:        }
1.11      thorpej   781:
1.1       hpeyerl   782:        /*
                    783:         * Fill in the component buf structure.
                    784:         */
1.63      thorpej   785:        cbp = CCD_GETBUF();
1.55      thorpej   786:        if (cbp == NULL)
                    787:                return (NULL);
1.6       cgd       788:        cbp->cb_buf.b_flags = bp->b_flags | B_CALL;
1.29      christos  789:        cbp->cb_buf.b_iodone = ccdiodone;
1.6       cgd       790:        cbp->cb_buf.b_proc = bp->b_proc;
1.11      thorpej   791:        cbp->cb_buf.b_dev = ci->ci_dev;         /* XXX */
1.6       cgd       792:        cbp->cb_buf.b_blkno = cbn + cboff;
                    793:        cbp->cb_buf.b_data = addr;
1.11      thorpej   794:        cbp->cb_buf.b_vp = ci->ci_vp;
1.65      fvdl      795:        LIST_INIT(&cbp->cb_buf.b_dep);
1.1       hpeyerl   796:        if (cs->sc_ileave == 0)
1.50      thorpej   797:                cbc = dbtob((u_int64_t)(ci->ci_size - cbn));
1.1       hpeyerl   798:        else
1.50      thorpej   799:                cbc = dbtob((u_int64_t)(cs->sc_ileave - cboff));
                    800:        cbp->cb_buf.b_bcount = cbc < bcount ? cbc : bcount;
1.6       cgd       801:
1.1       hpeyerl   802:        /*
1.6       cgd       803:         * context for ccdiodone
1.1       hpeyerl   804:         */
1.6       cgd       805:        cbp->cb_obp = bp;
1.59      thorpej   806:        cbp->cb_sc = cs;
1.36      thorpej   807:        cbp->cb_comp = ccdisk;
1.6       cgd       808:
1.1       hpeyerl   809: #ifdef DEBUG
1.3       hpeyerl   810:        if (ccddebug & CCDB_IO)
1.62      mjacob    811:                printf(" dev 0x%x(u%lu): cbp %p bn %d addr %p bcnt %ld\n",
                    812:                    ci->ci_dev, (unsigned long) (ci-cs->sc_cinfo), cbp,
                    813:                    cbp->cb_buf.b_blkno, cbp->cb_buf.b_data,
                    814:                    cbp->cb_buf.b_bcount);
1.1       hpeyerl   815: #endif
1.55      thorpej   816:
                    817:        return (cbp);
1.1       hpeyerl   818: }
                    819:
1.11      thorpej   820: static void
1.3       hpeyerl   821: ccdintr(cs, bp)
1.68      augustss  822:        struct ccd_softc *cs;
                    823:        struct buf *bp;
1.1       hpeyerl   824: {
                    825:
                    826: #ifdef DEBUG
1.3       hpeyerl   827:        if (ccddebug & CCDB_FOLLOW)
1.35      christos  828:                printf("ccdintr(%p, %p)\n", cs, bp);
1.1       hpeyerl   829: #endif
                    830:        /*
                    831:         * Request is done for better or worse, wakeup the top half.
                    832:         */
                    833:        if (bp->b_flags & B_ERROR)
                    834:                bp->b_resid = bp->b_bcount;
1.23      thorpej   835:        disk_unbusy(&cs->sc_dkdev, (bp->b_bcount - bp->b_resid));
1.1       hpeyerl   836:        biodone(bp);
                    837: }
                    838:
                    839: /*
1.11      thorpej   840:  * Called at interrupt time.
1.1       hpeyerl   841:  * Mark the component as done and if all components are done,
                    842:  * take a ccd interrupt.
                    843:  */
1.3       hpeyerl   844: void
1.29      christos  845: ccdiodone(vbp)
                    846:        struct buf *vbp;
1.1       hpeyerl   847: {
1.29      christos  848:        struct ccdbuf *cbp = (struct ccdbuf *) vbp;
1.59      thorpej   849:        struct buf *bp = cbp->cb_obp;
                    850:        struct ccd_softc *cs = cbp->cb_sc;
1.53      thorpej   851:        int count, s;
1.1       hpeyerl   852:
                    853:        s = splbio();
                    854: #ifdef DEBUG
1.3       hpeyerl   855:        if (ccddebug & CCDB_FOLLOW)
1.35      christos  856:                printf("ccdiodone(%p)\n", cbp);
1.3       hpeyerl   857:        if (ccddebug & CCDB_IO) {
1.53      thorpej   858:                printf("ccdiodone: bp %p bcount %ld resid %ld\n",
                    859:                       bp, bp->b_bcount, bp->b_resid);
1.43      fair      860:                printf(" dev 0x%x(u%d), cbp %p bn %d addr %p bcnt %ld\n",
1.6       cgd       861:                       cbp->cb_buf.b_dev, cbp->cb_comp, cbp,
                    862:                       cbp->cb_buf.b_blkno, cbp->cb_buf.b_data,
                    863:                       cbp->cb_buf.b_bcount);
1.1       hpeyerl   864:        }
                    865: #endif
                    866:
1.6       cgd       867:        if (cbp->cb_buf.b_flags & B_ERROR) {
1.53      thorpej   868:                bp->b_flags |= B_ERROR;
                    869:                bp->b_error = cbp->cb_buf.b_error ?
                    870:                    cbp->cb_buf.b_error : EIO;
1.24      thorpej   871:
1.53      thorpej   872:                printf("%s: error %d on component %d\n",
                    873:                       cs->sc_xname, bp->b_error, cbp->cb_comp);
1.1       hpeyerl   874:        }
1.6       cgd       875:        count = cbp->cb_buf.b_bcount;
1.63      thorpej   876:        CCD_PUTBUF(cbp);
1.1       hpeyerl   877:
                    878:        /*
                    879:         * If all done, "interrupt".
1.53      thorpej   880:         */
                    881:        bp->b_resid -= count;
                    882:        if (bp->b_resid < 0)
                    883:                panic("ccdiodone: count");
                    884:        if (bp->b_resid == 0)
1.59      thorpej   885:                ccdintr(cs, bp);
1.1       hpeyerl   886:        splx(s);
                    887: }
                    888:
1.11      thorpej   889: /* ARGSUSED */
1.10      mycroft   890: int
1.11      thorpej   891: ccdread(dev, uio, flags)
1.3       hpeyerl   892:        dev_t dev;
                    893:        struct uio *uio;
1.11      thorpej   894:        int flags;
1.3       hpeyerl   895: {
1.11      thorpej   896:        int unit = ccdunit(dev);
                    897:        struct ccd_softc *cs;
1.3       hpeyerl   898:
                    899: #ifdef DEBUG
                    900:        if (ccddebug & CCDB_FOLLOW)
1.43      fair      901:                printf("ccdread(0x%x, %p)\n", dev, uio);
1.3       hpeyerl   902: #endif
1.11      thorpej   903:        if (unit >= numccd)
                    904:                return (ENXIO);
                    905:        cs = &ccd_softc[unit];
                    906:
                    907:        if ((cs->sc_flags & CCDF_INITED) == 0)
                    908:                return (ENXIO);
                    909:
                    910:        /*
                    911:         * XXX: It's not clear that using minphys() is completely safe,
                    912:         * in particular, for raw I/O.  Underlying devices might have some
                    913:         * non-obvious limits, because of the copy to user-space.
                    914:         */
1.10      mycroft   915:        return (physio(ccdstrategy, NULL, dev, B_READ, minphys, uio));
1.3       hpeyerl   916: }
                    917:
1.11      thorpej   918: /* ARGSUSED */
1.10      mycroft   919: int
1.11      thorpej   920: ccdwrite(dev, uio, flags)
1.3       hpeyerl   921:        dev_t dev;
                    922:        struct uio *uio;
1.11      thorpej   923:        int flags;
1.3       hpeyerl   924: {
1.11      thorpej   925:        int unit = ccdunit(dev);
                    926:        struct ccd_softc *cs;
1.3       hpeyerl   927:
                    928: #ifdef DEBUG
                    929:        if (ccddebug & CCDB_FOLLOW)
1.43      fair      930:                printf("ccdwrite(0x%x, %p)\n", dev, uio);
1.3       hpeyerl   931: #endif
1.11      thorpej   932:        if (unit >= numccd)
                    933:                return (ENXIO);
                    934:        cs = &ccd_softc[unit];
                    935:
                    936:        if ((cs->sc_flags & CCDF_INITED) == 0)
                    937:                return (ENXIO);
                    938:
                    939:        /*
                    940:         * XXX: It's not clear that using minphys() is completely safe,
                    941:         * in particular, for raw I/O.  Underlying devices might have some
                    942:         * non-obvious limits, because of the copy to user-space.
                    943:         */
1.10      mycroft   944:        return (physio(ccdstrategy, NULL, dev, B_WRITE, minphys, uio));
1.3       hpeyerl   945: }
                    946:
1.11      thorpej   947: int
                    948: ccdioctl(dev, cmd, data, flag, p)
1.1       hpeyerl   949:        dev_t dev;
1.5       cgd       950:        u_long cmd;
1.1       hpeyerl   951:        caddr_t data;
                    952:        int flag;
1.11      thorpej   953:        struct proc *p;
1.1       hpeyerl   954: {
1.11      thorpej   955:        int unit = ccdunit(dev);
1.57      thorpej   956:        int i, j, lookedup = 0, error;
1.39      mycroft   957:        int part, pmask;
1.11      thorpej   958:        struct ccd_softc *cs;
                    959:        struct ccd_ioctl *ccio = (struct ccd_ioctl *)data;
                    960:        char **cpp;
                    961:        struct vnode **vpp;
1.70      fvdl      962: #ifdef __HAVE_OLD_DISKLABEL
                    963:        struct disklabel newlabel;
                    964: #endif
1.11      thorpej   965:
                    966:        if (unit >= numccd)
                    967:                return (ENXIO);
                    968:        cs = &ccd_softc[unit];
                    969:
1.41      thorpej   970:        /* Must be open for writes for these commands... */
                    971:        switch (cmd) {
                    972:        case CCDIOCSET:
                    973:        case CCDIOCCLR:
                    974:        case DIOCSDINFO:
                    975:        case DIOCWDINFO:
1.70      fvdl      976: #ifdef __HAVE_OLD_DISKLABEL
                    977:        case ODIOCSDINFO:
                    978:        case ODIOCWDINFO:
                    979: #endif
1.41      thorpej   980:        case DIOCWLABEL:
                    981:                if ((flag & FWRITE) == 0)
                    982:                        return (EBADF);
                    983:        }
                    984:
1.57      thorpej   985:        if ((error = lockmgr(&cs->sc_lock, LK_EXCLUSIVE, NULL)) != 0)
                    986:                return (error);
                    987:
1.41      thorpej   988:        /* Must be initialized for these... */
                    989:        switch (cmd) {
                    990:        case CCDIOCCLR:
1.42      kleink    991:        case DIOCGDINFO:
                    992:        case DIOCSDINFO:
                    993:        case DIOCWDINFO:
                    994:        case DIOCGPART:
1.41      thorpej   995:        case DIOCWLABEL:
1.44      thorpej   996:        case DIOCGDEFLABEL:
1.70      fvdl      997: #ifdef __HAVE_OLD_DISKLABEL
                    998:        case ODIOCGDINFO:
                    999:        case ODIOCSDINFO:
                   1000:        case ODIOCWDINFO:
                   1001:        case ODIOCGDEFLABEL:
                   1002: #endif
1.57      thorpej  1003:                if ((cs->sc_flags & CCDF_INITED) == 0) {
                   1004:                        error = ENXIO;
                   1005:                        goto out;
                   1006:                }
1.41      thorpej  1007:        }
                   1008:
1.11      thorpej  1009:        switch (cmd) {
                   1010:        case CCDIOCSET:
1.57      thorpej  1011:                if (cs->sc_flags & CCDF_INITED) {
                   1012:                        error = EBUSY;
                   1013:                        goto out;
                   1014:                }
1.54      thorpej  1015:
                   1016:                /* Validate the flags. */
1.57      thorpej  1017:                if ((ccio->ccio_flags & CCDF_USERMASK) != ccio->ccio_flags) {
                   1018:                        error = EINVAL;
                   1019:                        goto out;
                   1020:                }
1.15      thorpej  1021:
1.72.2.1  thorpej  1022:                if (ccio->ccio_ndisks > CCD_MAXNDISKS) {
                   1023:                        error = EINVAL;
                   1024:                        goto out;
                   1025:                }
                   1026:
1.11      thorpej  1027:                /* Fill in some important bits. */
1.57      thorpej  1028:                cs->sc_ileave = ccio->ccio_ileave;
                   1029:                cs->sc_nccdisks = ccio->ccio_ndisks;
                   1030:                cs->sc_flags = ccio->ccio_flags & CCDF_USERMASK;
1.11      thorpej  1031:
                   1032:                /*
                   1033:                 * Allocate space for and copy in the array of
                   1034:                 * componet pathnames and device numbers.
                   1035:                 */
                   1036:                cpp = malloc(ccio->ccio_ndisks * sizeof(char *),
                   1037:                    M_DEVBUF, M_WAITOK);
                   1038:                vpp = malloc(ccio->ccio_ndisks * sizeof(struct vnode *),
                   1039:                    M_DEVBUF, M_WAITOK);
                   1040:
                   1041:                error = copyin((caddr_t)ccio->ccio_disks, (caddr_t)cpp,
                   1042:                    ccio->ccio_ndisks * sizeof(char **));
                   1043:                if (error) {
                   1044:                        free(vpp, M_DEVBUF);
                   1045:                        free(cpp, M_DEVBUF);
1.57      thorpej  1046:                        goto out;
1.11      thorpej  1047:                }
                   1048:
                   1049: #ifdef DEBUG
                   1050:                if (ccddebug & CCDB_INIT)
                   1051:                        for (i = 0; i < ccio->ccio_ndisks; ++i)
1.35      christos 1052:                                printf("ccdioctl: component %d: 0x%p\n",
1.11      thorpej  1053:                                    i, cpp[i]);
                   1054: #endif
                   1055:
                   1056:                for (i = 0; i < ccio->ccio_ndisks; ++i) {
                   1057: #ifdef DEBUG
                   1058:                        if (ccddebug & CCDB_INIT)
1.35      christos 1059:                                printf("ccdioctl: lookedup = %d\n", lookedup);
1.11      thorpej  1060: #endif
1.29      christos 1061:                        if ((error = ccdlookup(cpp[i], p, &vpp[i])) != 0) {
1.11      thorpej  1062:                                for (j = 0; j < lookedup; ++j)
1.12      thorpej  1063:                                        (void)vn_close(vpp[j], FREAD|FWRITE,
1.11      thorpej  1064:                                            p->p_ucred, p);
                   1065:                                free(vpp, M_DEVBUF);
                   1066:                                free(cpp, M_DEVBUF);
1.57      thorpej  1067:                                goto out;
1.11      thorpej  1068:                        }
                   1069:                        ++lookedup;
                   1070:                }
                   1071:
                   1072:                /*
                   1073:                 * Initialize the ccd.  Fills in the softc for us.
                   1074:                 */
1.57      thorpej  1075:                if ((error = ccdinit(cs, cpp, vpp, p)) != 0) {
1.11      thorpej  1076:                        for (j = 0; j < lookedup; ++j)
1.18      thorpej  1077:                                (void)vn_close(vpp[j], FREAD|FWRITE,
1.11      thorpej  1078:                                    p->p_ucred, p);
                   1079:                        free(vpp, M_DEVBUF);
                   1080:                        free(cpp, M_DEVBUF);
1.57      thorpej  1081:                        goto out;
1.11      thorpej  1082:                }
                   1083:
1.57      thorpej  1084:                /* We can free the temporary variables now. */
                   1085:                free(vpp, M_DEVBUF);
                   1086:                free(cpp, M_DEVBUF);
                   1087:
1.11      thorpej  1088:                /*
                   1089:                 * The ccd has been successfully initialized, so
1.23      thorpej  1090:                 * we can place it into the array.  Don't try to
                   1091:                 * read the disklabel until the disk has been attached,
                   1092:                 * because space for the disklabel is allocated
                   1093:                 * in disk_attach();
1.11      thorpej  1094:                 */
                   1095:                ccio->ccio_unit = unit;
                   1096:                ccio->ccio_size = cs->sc_size;
1.23      thorpej  1097:
                   1098:                /* Attach the disk. */
                   1099:                disk_attach(&cs->sc_dkdev);
                   1100:
                   1101:                /* Try and read the disklabel. */
1.11      thorpej  1102:                ccdgetdisklabel(dev);
                   1103:                break;
                   1104:
                   1105:        case CCDIOCCLR:
                   1106:                /*
                   1107:                 * Don't unconfigure if any other partitions are open
                   1108:                 * or if both the character and block flavors of this
                   1109:                 * partition are open.
                   1110:                 */
                   1111:                part = DISKPART(dev);
                   1112:                pmask = (1 << part);
                   1113:                if ((cs->sc_dkdev.dk_openmask & ~pmask) ||
                   1114:                    ((cs->sc_dkdev.dk_bopenmask & pmask) &&
1.15      thorpej  1115:                    (cs->sc_dkdev.dk_copenmask & pmask))) {
1.57      thorpej  1116:                        error = EBUSY;
                   1117:                        goto out;
1.15      thorpej  1118:                }
1.11      thorpej  1119:
                   1120:                /*
                   1121:                 * Free ccd_softc information and clear entry.
                   1122:                 */
1.22      thorpej  1123:
                   1124:                /* Close the components and free their pathnames. */
1.11      thorpej  1125:                for (i = 0; i < cs->sc_nccdisks; ++i) {
                   1126:                        /*
                   1127:                         * XXX: this close could potentially fail and
                   1128:                         * cause Bad Things.  Maybe we need to force
                   1129:                         * the close to happen?
                   1130:                         */
                   1131: #ifdef DEBUG
                   1132:                        if (ccddebug & CCDB_VNODE)
                   1133:                                vprint("CCDIOCCLR: vnode info",
                   1134:                                    cs->sc_cinfo[i].ci_vp);
                   1135: #endif
                   1136:                        (void)vn_close(cs->sc_cinfo[i].ci_vp, FREAD|FWRITE,
                   1137:                            p->p_ucred, p);
                   1138:                        free(cs->sc_cinfo[i].ci_path, M_DEVBUF);
1.38      thorpej  1139:                }
                   1140:
1.22      thorpej  1141:                /* Free interleave index. */
                   1142:                for (i = 0; cs->sc_itable[i].ii_ndisk; ++i)
1.19      thorpej  1143:                        free(cs->sc_itable[i].ii_index, M_DEVBUF);
1.22      thorpej  1144:
                   1145:                /* Free component info and interleave table. */
1.11      thorpej  1146:                free(cs->sc_cinfo, M_DEVBUF);
                   1147:                free(cs->sc_itable, M_DEVBUF);
1.21      thorpej  1148:                cs->sc_flags &= ~CCDF_INITED;
1.15      thorpej  1149:
1.23      thorpej  1150:                /* Detatch the disk. */
1.26      hpeyerl  1151:                disk_detach(&cs->sc_dkdev);
1.11      thorpej  1152:                break;
                   1153:
                   1154:        case DIOCGDINFO:
1.23      thorpej  1155:                *(struct disklabel *)data = *(cs->sc_dkdev.dk_label);
1.11      thorpej  1156:                break;
1.70      fvdl     1157: #ifdef __HAVE_OLD_DISKLABEL
                   1158:        case ODIOCGDINFO:
                   1159:                newlabel = *(cs->sc_dkdev.dk_label);
                   1160:                if (newlabel.d_npartitions > OLDMAXPARTITIONS)
1.71      fvdl     1161:                        return ENOTTY;
1.70      fvdl     1162:                memcpy(data, &newlabel, sizeof (struct olddisklabel));
                   1163:                break;
                   1164: #endif
1.11      thorpej  1165:
                   1166:        case DIOCGPART:
1.23      thorpej  1167:                ((struct partinfo *)data)->disklab = cs->sc_dkdev.dk_label;
1.11      thorpej  1168:                ((struct partinfo *)data)->part =
1.23      thorpej  1169:                    &cs->sc_dkdev.dk_label->d_partitions[DISKPART(dev)];
1.11      thorpej  1170:                break;
                   1171:
                   1172:        case DIOCWDINFO:
                   1173:        case DIOCSDINFO:
1.70      fvdl     1174: #ifdef __HAVE_OLD_DISKLABEL
                   1175:        case ODIOCWDINFO:
                   1176:        case ODIOCSDINFO:
                   1177: #endif
                   1178:        {
                   1179:                struct disklabel *lp;
                   1180: #ifdef __HAVE_OLD_DISKLABEL
                   1181:                if (cmd == ODIOCSDINFO || cmd == ODIOCWDINFO) {
                   1182:                        memset(&newlabel, 0, sizeof newlabel);
                   1183:                        memcpy(&newlabel, data, sizeof (struct olddisklabel));
                   1184:                        lp = &newlabel;
                   1185:                } else
                   1186: #endif
                   1187:                lp = (struct disklabel *)data;
                   1188:
1.11      thorpej  1189:                cs->sc_flags |= CCDF_LABELLING;
                   1190:
1.23      thorpej  1191:                error = setdisklabel(cs->sc_dkdev.dk_label,
1.70      fvdl     1192:                    lp, 0, cs->sc_dkdev.dk_cpulabel);
1.11      thorpej  1193:                if (error == 0) {
1.70      fvdl     1194:                        if (cmd == DIOCWDINFO
                   1195: #ifdef __HAVE_OLD_DISKLABEL
                   1196:                            || cmd == ODIOCWDINFO
                   1197: #endif
                   1198:                           )
1.11      thorpej  1199:                                error = writedisklabel(CCDLABELDEV(dev),
1.23      thorpej  1200:                                    ccdstrategy, cs->sc_dkdev.dk_label,
                   1201:                                    cs->sc_dkdev.dk_cpulabel);
1.11      thorpej  1202:                }
                   1203:
                   1204:                cs->sc_flags &= ~CCDF_LABELLING;
                   1205:                break;
1.70      fvdl     1206:        }
1.11      thorpej  1207:
                   1208:        case DIOCWLABEL:
                   1209:                if (*(int *)data != 0)
                   1210:                        cs->sc_flags |= CCDF_WLABEL;
                   1211:                else
                   1212:                        cs->sc_flags &= ~CCDF_WLABEL;
                   1213:                break;
                   1214:
1.44      thorpej  1215:        case DIOCGDEFLABEL:
                   1216:                ccdgetdefaultlabel(cs, (struct disklabel *)data);
                   1217:                break;
1.70      fvdl     1218:
                   1219: #ifdef __HAVE_OLD_DISKLABEL
                   1220:        case ODIOCGDEFLABEL:
                   1221:                ccdgetdefaultlabel(cs, &newlabel);
                   1222:                if (newlabel.d_npartitions > OLDMAXPARTITIONS)
1.71      fvdl     1223:                        return ENOTTY;
1.70      fvdl     1224:                memcpy(data, &newlabel, sizeof (struct olddisklabel));
                   1225:                break;
                   1226: #endif
1.44      thorpej  1227:
1.11      thorpej  1228:        default:
1.57      thorpej  1229:                error = ENOTTY;
1.11      thorpej  1230:        }
                   1231:
1.57      thorpej  1232:  out:
                   1233:        (void) lockmgr(&cs->sc_lock, LK_RELEASE, NULL);
                   1234:        return (error);
1.1       hpeyerl  1235: }
                   1236:
1.11      thorpej  1237: int
1.1       hpeyerl  1238: ccdsize(dev)
                   1239:        dev_t dev;
                   1240: {
1.11      thorpej  1241:        struct ccd_softc *cs;
1.40      thorpej  1242:        struct disklabel *lp;
                   1243:        int part, unit, omask, size;
                   1244:
                   1245:        unit = ccdunit(dev);
                   1246:        if (unit >= numccd)
                   1247:                return (-1);
                   1248:        cs = &ccd_softc[unit];
1.11      thorpej  1249:
1.40      thorpej  1250:        if ((cs->sc_flags & CCDF_INITED) == 0)
1.11      thorpej  1251:                return (-1);
                   1252:
                   1253:        part = DISKPART(dev);
1.40      thorpej  1254:        omask = cs->sc_dkdev.dk_openmask & (1 << part);
                   1255:        lp = cs->sc_dkdev.dk_label;
1.11      thorpej  1256:
1.40      thorpej  1257:        if (omask == 0 && ccdopen(dev, 0, S_IFBLK, curproc))
1.11      thorpej  1258:                return (-1);
                   1259:
1.40      thorpej  1260:        if (lp->d_partitions[part].p_fstype != FS_SWAP)
1.11      thorpej  1261:                size = -1;
                   1262:        else
1.40      thorpej  1263:                size = lp->d_partitions[part].p_size *
                   1264:                    (lp->d_secsize / DEV_BSIZE);
1.11      thorpej  1265:
1.40      thorpej  1266:        if (omask == 0 && ccdclose(dev, 0, S_IFBLK, curproc))
1.11      thorpej  1267:                return (-1);
1.1       hpeyerl  1268:
1.11      thorpej  1269:        return (size);
1.1       hpeyerl  1270: }
                   1271:
1.9       cgd      1272: int
                   1273: ccddump(dev, blkno, va, size)
                   1274:        dev_t dev;
                   1275:        daddr_t blkno;
                   1276:        caddr_t va;
                   1277:        size_t size;
1.1       hpeyerl  1278: {
1.9       cgd      1279:
                   1280:        /* Not implemented. */
                   1281:        return ENXIO;
1.11      thorpej  1282: }
                   1283:
                   1284: /*
                   1285:  * Lookup the provided name in the filesystem.  If the file exists,
                   1286:  * is a valid block device, and isn't being used by anyone else,
                   1287:  * set *vpp to the file's vnode.
                   1288:  */
                   1289: static int
                   1290: ccdlookup(path, p, vpp)
                   1291:        char *path;
                   1292:        struct proc *p;
                   1293:        struct vnode **vpp;     /* result */
                   1294: {
                   1295:        struct nameidata nd;
                   1296:        struct vnode *vp;
                   1297:        struct vattr va;
                   1298:        int error;
                   1299:
                   1300:        NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, path, p);
1.29      christos 1301:        if ((error = vn_open(&nd, FREAD|FWRITE, 0)) != 0) {
1.11      thorpej  1302: #ifdef DEBUG
1.29      christos 1303:                if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))
1.35      christos 1304:                        printf("ccdlookup: vn_open error = %d\n", error);
1.11      thorpej  1305: #endif
                   1306:                return (error);
                   1307:        }
                   1308:        vp = nd.ni_vp;
                   1309:
                   1310:        if (vp->v_usecount > 1) {
1.49      ross     1311:                VOP_UNLOCK(vp, 0);
1.11      thorpej  1312:                (void)vn_close(vp, FREAD|FWRITE, p->p_ucred, p);
                   1313:                return (EBUSY);
                   1314:        }
                   1315:
1.29      christos 1316:        if ((error = VOP_GETATTR(vp, &va, p->p_ucred, p)) != 0) {
1.11      thorpej  1317: #ifdef DEBUG
1.29      christos 1318:                if (ccddebug & (CCDB_FOLLOW|CCDB_INIT))
1.35      christos 1319:                        printf("ccdlookup: getattr error = %d\n", error);
1.11      thorpej  1320: #endif
1.49      ross     1321:                VOP_UNLOCK(vp, 0);
1.11      thorpej  1322:                (void)vn_close(vp, FREAD|FWRITE, p->p_ucred, p);
                   1323:                return (error);
                   1324:        }
                   1325:
                   1326:        /* XXX: eventually we should handle VREG, too. */
                   1327:        if (va.va_type != VBLK) {
1.49      ross     1328:                VOP_UNLOCK(vp, 0);
1.11      thorpej  1329:                (void)vn_close(vp, FREAD|FWRITE, p->p_ucred, p);
                   1330:                return (ENOTBLK);
                   1331:        }
                   1332:
                   1333: #ifdef DEBUG
                   1334:        if (ccddebug & CCDB_VNODE)
                   1335:                vprint("ccdlookup: vnode info", vp);
                   1336: #endif
                   1337:
1.49      ross     1338:        VOP_UNLOCK(vp, 0);
1.11      thorpej  1339:        *vpp = vp;
                   1340:        return (0);
                   1341: }
                   1342:
                   1343: static void
1.44      thorpej  1344: ccdgetdefaultlabel(cs, lp)
                   1345:        struct ccd_softc *cs;
                   1346:        struct disklabel *lp;
1.11      thorpej  1347: {
                   1348:        struct ccdgeom *ccg = &cs->sc_geom;
                   1349:
1.72      thorpej  1350:        memset(lp, 0, sizeof(*lp));
1.11      thorpej  1351:
                   1352:        lp->d_secperunit = cs->sc_size;
                   1353:        lp->d_secsize = ccg->ccg_secsize;
                   1354:        lp->d_nsectors = ccg->ccg_nsectors;
                   1355:        lp->d_ntracks = ccg->ccg_ntracks;
                   1356:        lp->d_ncylinders = ccg->ccg_ncylinders;
1.19      thorpej  1357:        lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors;
1.11      thorpej  1358:
                   1359:        strncpy(lp->d_typename, "ccd", sizeof(lp->d_typename));
                   1360:        lp->d_type = DTYPE_CCD;
                   1361:        strncpy(lp->d_packname, "fictitious", sizeof(lp->d_packname));
                   1362:        lp->d_rpm = 3600;
                   1363:        lp->d_interleave = 1;
                   1364:        lp->d_flags = 0;
                   1365:
                   1366:        lp->d_partitions[RAW_PART].p_offset = 0;
                   1367:        lp->d_partitions[RAW_PART].p_size = cs->sc_size;
                   1368:        lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED;
                   1369:        lp->d_npartitions = RAW_PART + 1;
                   1370:
                   1371:        lp->d_magic = DISKMAGIC;
                   1372:        lp->d_magic2 = DISKMAGIC;
1.23      thorpej  1373:        lp->d_checksum = dkcksum(cs->sc_dkdev.dk_label);
1.44      thorpej  1374: }
                   1375:
                   1376: /*
                   1377:  * Read the disklabel from the ccd.  If one is not present, fake one
                   1378:  * up.
                   1379:  */
                   1380: static void
                   1381: ccdgetdisklabel(dev)
                   1382:        dev_t dev;
                   1383: {
                   1384:        int unit = ccdunit(dev);
                   1385:        struct ccd_softc *cs = &ccd_softc[unit];
                   1386:        char *errstring;
                   1387:        struct disklabel *lp = cs->sc_dkdev.dk_label;
                   1388:        struct cpu_disklabel *clp = cs->sc_dkdev.dk_cpulabel;
                   1389:
1.72      thorpej  1390:        memset(clp, 0, sizeof(*clp));
1.44      thorpej  1391:
                   1392:        ccdgetdefaultlabel(cs, lp);
1.11      thorpej  1393:
                   1394:        /*
                   1395:         * Call the generic disklabel extraction routine.
                   1396:         */
1.29      christos 1397:        errstring = readdisklabel(CCDLABELDEV(dev), ccdstrategy,
                   1398:            cs->sc_dkdev.dk_label, cs->sc_dkdev.dk_cpulabel);
                   1399:        if (errstring)
1.11      thorpej  1400:                ccdmakedisklabel(cs);
1.47      enami    1401:        else {
                   1402:                int i;
                   1403:                struct partition *pp;
                   1404:
                   1405:                /*
                   1406:                 * Sanity check whether the found disklabel is valid.
                   1407:                 *
                   1408:                 * This is necessary since total size of ccd may vary
                   1409:                 * when an interleave is changed even though exactly
                   1410:                 * same componets are used, and old disklabel may used
                   1411:                 * if that is found.
                   1412:                 */
                   1413:                if (lp->d_secperunit != cs->sc_size)
                   1414:                        printf("WARNING: %s: "
                   1415:                            "total sector size in disklabel (%d) != "
1.60      thorpej  1416:                            "the size of ccd (%lu)\n", cs->sc_xname,
                   1417:                            lp->d_secperunit, (u_long)cs->sc_size);
1.47      enami    1418:                for (i = 0; i < lp->d_npartitions; i++) {
                   1419:                        pp = &lp->d_partitions[i];
                   1420:                        if (pp->p_offset + pp->p_size > cs->sc_size)
1.48      enami    1421:                                printf("WARNING: %s: end of partition `%c' "
1.60      thorpej  1422:                                    "exceeds the size of ccd (%lu)\n",
                   1423:                                    cs->sc_xname, 'a' + i, (u_long)cs->sc_size);
1.47      enami    1424:                }
                   1425:        }
1.11      thorpej  1426:
                   1427: #ifdef DEBUG
                   1428:        /* It's actually extremely common to have unlabeled ccds. */
                   1429:        if (ccddebug & CCDB_LABEL)
                   1430:                if (errstring != NULL)
1.35      christos 1431:                        printf("%s: %s\n", cs->sc_xname, errstring);
1.11      thorpej  1432: #endif
                   1433: }
                   1434:
                   1435: /*
                   1436:  * Take care of things one might want to take care of in the event
                   1437:  * that a disklabel isn't present.
                   1438:  */
                   1439: static void
                   1440: ccdmakedisklabel(cs)
                   1441:        struct ccd_softc *cs;
                   1442: {
1.23      thorpej  1443:        struct disklabel *lp = cs->sc_dkdev.dk_label;
1.11      thorpej  1444:
                   1445:        /*
                   1446:         * For historical reasons, if there's no disklabel present
                   1447:         * the raw partition must be marked FS_BSDFFS.
                   1448:         */
                   1449:        lp->d_partitions[RAW_PART].p_fstype = FS_BSDFFS;
                   1450:
                   1451:        strncpy(lp->d_packname, "default label", sizeof(lp->d_packname));
1.44      thorpej  1452:
                   1453:        lp->d_checksum = dkcksum(lp);
1.11      thorpej  1454: }
                   1455:
                   1456: #ifdef DEBUG
                   1457: static void
                   1458: printiinfo(ii)
                   1459:        struct ccdiinfo *ii;
                   1460: {
1.68      augustss 1461:        int ix, i;
1.11      thorpej  1462:
                   1463:        for (ix = 0; ii->ii_ndisk; ix++, ii++) {
1.35      christos 1464:                printf(" itab[%d]: #dk %d sblk %d soff %d",
1.34      christos 1465:                    ix, ii->ii_ndisk, ii->ii_startblk, ii->ii_startoff);
1.11      thorpej  1466:                for (i = 0; i < ii->ii_ndisk; i++)
1.35      christos 1467:                        printf(" %d", ii->ii_index[i]);
                   1468:                printf("\n");
1.11      thorpej  1469:        }
1.1       hpeyerl  1470: }
                   1471: #endif

CVSweb <webmaster@jp.NetBSD.org>