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