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