13bc746beSSatoshi Asami /* $Id: ccd.c,v 1.5 1996/01/30 22:34:53 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> 95a56bb8a5SSatoshi Asami #include <sys/proc.h> 96a56bb8a5SSatoshi Asami #include <sys/errno.h> 97a56bb8a5SSatoshi Asami #include <sys/dkstat.h> 98a56bb8a5SSatoshi Asami #include <sys/buf.h> 99a56bb8a5SSatoshi Asami #include <sys/malloc.h> 100a56bb8a5SSatoshi Asami #include <sys/namei.h> 101a56bb8a5SSatoshi Asami #include <sys/conf.h> 102a56bb8a5SSatoshi Asami #include <sys/stat.h> 103a56bb8a5SSatoshi Asami #include <sys/ioctl.h> 104a56bb8a5SSatoshi Asami #include <sys/disklabel.h> 105d8594dfbSSatoshi Asami #include <ufs/ffs/fs.h> 106d8594dfbSSatoshi Asami #include <sys/devconf.h> 107a56bb8a5SSatoshi Asami #include <sys/device.h> 108a56bb8a5SSatoshi Asami #include <sys/disk.h> 109a56bb8a5SSatoshi Asami #include <sys/syslog.h> 110a56bb8a5SSatoshi Asami #include <sys/fcntl.h> 111a56bb8a5SSatoshi Asami #include <sys/vnode.h> 112d8594dfbSSatoshi Asami #include <sys/dkbad.h> 113a56bb8a5SSatoshi Asami 114d8594dfbSSatoshi Asami #include <sys/ccdvar.h> 115a56bb8a5SSatoshi Asami 116a56bb8a5SSatoshi Asami #if defined(CCDDEBUG) && !defined(DEBUG) 117a56bb8a5SSatoshi Asami #define DEBUG 118a56bb8a5SSatoshi Asami #endif 119a56bb8a5SSatoshi Asami 120a56bb8a5SSatoshi Asami #ifdef DEBUG 121a56bb8a5SSatoshi Asami #define CCDB_FOLLOW 0x01 122a56bb8a5SSatoshi Asami #define CCDB_INIT 0x02 123a56bb8a5SSatoshi Asami #define CCDB_IO 0x04 124a56bb8a5SSatoshi Asami #define CCDB_LABEL 0x08 125a56bb8a5SSatoshi Asami #define CCDB_VNODE 0x10 126d8594dfbSSatoshi Asami int ccddebug = CCDB_FOLLOW | CCDB_INIT | CCDB_IO | CCDB_LABEL | CCDB_VNODE; 127d8594dfbSSatoshi Asami #undef DEBUG 128a56bb8a5SSatoshi Asami #endif 129a56bb8a5SSatoshi Asami 130d8594dfbSSatoshi Asami #define ccdunit(x) dkunit(x) 131d8594dfbSSatoshi Asami #define ccdpart(x) dkpart(x) 132a56bb8a5SSatoshi Asami 133a56bb8a5SSatoshi Asami struct ccdbuf { 134a56bb8a5SSatoshi Asami struct buf cb_buf; /* new I/O buf */ 135a56bb8a5SSatoshi Asami struct buf *cb_obp; /* ptr. to original I/O buf */ 136a56bb8a5SSatoshi Asami int cb_unit; /* target unit */ 137a56bb8a5SSatoshi Asami int cb_comp; /* target component */ 138a56bb8a5SSatoshi Asami }; 139a56bb8a5SSatoshi Asami 140a56bb8a5SSatoshi Asami #define getccdbuf() \ 141a56bb8a5SSatoshi Asami ((struct ccdbuf *)malloc(sizeof(struct ccdbuf), M_DEVBUF, M_WAITOK)) 142a56bb8a5SSatoshi Asami #define putccdbuf(cbp) \ 143a56bb8a5SSatoshi Asami free((caddr_t)(cbp), M_DEVBUF) 144a56bb8a5SSatoshi Asami 145a56bb8a5SSatoshi Asami #define CCDLABELDEV(dev) \ 146d8594dfbSSatoshi Asami (makedev(major((dev)), dkmakeminor(ccdunit((dev)), 0, RAW_PART))) 147a56bb8a5SSatoshi Asami 148a56bb8a5SSatoshi Asami /* {b,c}devsw[] function prototypes */ 149d8594dfbSSatoshi Asami d_open_t ccdopen ; 150d8594dfbSSatoshi Asami d_close_t ccdclose ; 151d8594dfbSSatoshi Asami d_strategy_t ccdstrategy ; 152d8594dfbSSatoshi Asami d_ioctl_t ccdioctl ; 153d8594dfbSSatoshi Asami d_read_t ccdread ; 154d8594dfbSSatoshi Asami d_write_t ccdwrite ; 155d8594dfbSSatoshi Asami 156a56bb8a5SSatoshi Asami 157a56bb8a5SSatoshi Asami /* called by main() at boot time */ 158d8594dfbSSatoshi Asami int ccdattach __P((struct isa_device *dp)); 159d8594dfbSSatoshi Asami int ccdprobe __P((struct isa_device *dp)); 160a56bb8a5SSatoshi Asami 161a56bb8a5SSatoshi Asami /* called by biodone() at interrupt time */ 162a56bb8a5SSatoshi Asami void ccdiodone __P((struct ccdbuf *cbp)); 163a56bb8a5SSatoshi Asami 164a56bb8a5SSatoshi Asami static void ccdstart __P((struct ccd_softc *, struct buf *)); 165a56bb8a5SSatoshi Asami static void ccdinterleave __P((struct ccd_softc *, int)); 166a56bb8a5SSatoshi Asami static void ccdintr __P((struct ccd_softc *, struct buf *)); 167a56bb8a5SSatoshi Asami static int ccdinit __P((struct ccddevice *, char **, struct proc *)); 168a56bb8a5SSatoshi Asami static int ccdlookup __P((char *, struct proc *p, struct vnode **)); 1693bc746beSSatoshi Asami static void ccdbuffer __P((struct ccdbuf **ret, struct ccd_softc *, 1703bc746beSSatoshi Asami struct buf *, daddr_t, caddr_t, long)); 171a56bb8a5SSatoshi Asami static void ccdgetdisklabel __P((dev_t)); 172a56bb8a5SSatoshi Asami static void ccdmakedisklabel __P((struct ccd_softc *)); 173a56bb8a5SSatoshi Asami static int ccdlock __P((struct ccd_softc *)); 174a56bb8a5SSatoshi Asami static void ccdunlock __P((struct ccd_softc *)); 175a56bb8a5SSatoshi Asami 176d8594dfbSSatoshi Asami static void loopdelay __P((void)); 177d8594dfbSSatoshi Asami 178a56bb8a5SSatoshi Asami #ifdef DEBUG 179a56bb8a5SSatoshi Asami static void printiinfo __P((struct ccdiinfo *)); 180a56bb8a5SSatoshi Asami #endif 181a56bb8a5SSatoshi Asami 182a56bb8a5SSatoshi Asami /* Non-private for the benefit of libkvm. */ 183a56bb8a5SSatoshi Asami struct ccd_softc *ccd_softc; 184a56bb8a5SSatoshi Asami struct ccddevice *ccddevs; 185a56bb8a5SSatoshi Asami int numccd = 0; 186a56bb8a5SSatoshi Asami 187d8594dfbSSatoshi Asami static struct kern_devconf kdc_ccd[NCCD] = { { 188d8594dfbSSatoshi Asami 0, 0, 0, /* filled in by dev_attach */ 189d8594dfbSSatoshi Asami "ccd", 0, { MDDT_DISK, 0, "tty" }, 190d8594dfbSSatoshi Asami 0, 0, 0, DISK_EXTERNALLEN, 191d8594dfbSSatoshi Asami 0, /* parent */ 192d8594dfbSSatoshi Asami 0, /* parentdata */ 193d8594dfbSSatoshi Asami DC_UNKNOWN, /* not supported */ 194d8594dfbSSatoshi Asami "Concatenated disk driver" 195d8594dfbSSatoshi Asami } }; 196d8594dfbSSatoshi Asami 197d8594dfbSSatoshi Asami struct isa_driver ccddriver = { 198d8594dfbSSatoshi Asami ccdprobe, ccdattach, "ccd", 199d8594dfbSSatoshi Asami }; 200d8594dfbSSatoshi Asami 201d8594dfbSSatoshi Asami int 202d8594dfbSSatoshi Asami ccdprobe(dp) 203d8594dfbSSatoshi Asami struct isa_device *dp; 204d8594dfbSSatoshi Asami { 205d8594dfbSSatoshi Asami return -1; 206d8594dfbSSatoshi Asami } 207d8594dfbSSatoshi Asami 208a56bb8a5SSatoshi Asami /* 209a56bb8a5SSatoshi Asami * Called by main() during pseudo-device attachment. All we need 210a56bb8a5SSatoshi Asami * to do is allocate enough space for devices to be configured later. 211a56bb8a5SSatoshi Asami */ 212d8594dfbSSatoshi Asami int 213d8594dfbSSatoshi Asami ccdattach(dp) 214d8594dfbSSatoshi Asami struct isa_device *dp; 215a56bb8a5SSatoshi Asami { 216a56bb8a5SSatoshi Asami int i; 217d8594dfbSSatoshi Asami int num = dp->id_unit; 218a56bb8a5SSatoshi Asami 219d8594dfbSSatoshi Asami if (num < 0) { 220a56bb8a5SSatoshi Asami #ifdef DIAGNOSTIC 221a56bb8a5SSatoshi Asami panic("ccdattach: count <= 0"); 222a56bb8a5SSatoshi Asami #endif 223d8594dfbSSatoshi Asami return 0; 224a56bb8a5SSatoshi Asami } 225a56bb8a5SSatoshi Asami 226d8594dfbSSatoshi Asami if (num == NCCD-1) { 227d8594dfbSSatoshi Asami if (num) 228d8594dfbSSatoshi Asami printf("ccd0-%d: Concatenated disk drivers\n", num); 229d8594dfbSSatoshi Asami else 230d8594dfbSSatoshi Asami printf("ccd0: Concatenated disk driver\n", num); 231d8594dfbSSatoshi Asami } 232d8594dfbSSatoshi Asami 233d8594dfbSSatoshi Asami if (num > 0) { 234d8594dfbSSatoshi Asami /* only do initialization first time around */ 235d8594dfbSSatoshi Asami return 0; 236d8594dfbSSatoshi Asami } 237d8594dfbSSatoshi Asami num = NCCD; 238a56bb8a5SSatoshi Asami ccd_softc = (struct ccd_softc *)malloc(num * sizeof(struct ccd_softc), 239a56bb8a5SSatoshi Asami M_DEVBUF, M_NOWAIT); 240a56bb8a5SSatoshi Asami ccddevs = (struct ccddevice *)malloc(num * sizeof(struct ccddevice), 241a56bb8a5SSatoshi Asami M_DEVBUF, M_NOWAIT); 242a56bb8a5SSatoshi Asami if ((ccd_softc == NULL) || (ccddevs == NULL)) { 243a56bb8a5SSatoshi Asami printf("WARNING: no memory for concatenated disks\n"); 244a56bb8a5SSatoshi Asami if (ccd_softc != NULL) 245a56bb8a5SSatoshi Asami free(ccd_softc, M_DEVBUF); 246a56bb8a5SSatoshi Asami if (ccddevs != NULL) 247a56bb8a5SSatoshi Asami free(ccddevs, M_DEVBUF); 248d8594dfbSSatoshi Asami return 0; 249a56bb8a5SSatoshi Asami } 250a56bb8a5SSatoshi Asami numccd = num; 251a56bb8a5SSatoshi Asami bzero(ccd_softc, num * sizeof(struct ccd_softc)); 252a56bb8a5SSatoshi Asami bzero(ccddevs, num * sizeof(struct ccddevice)); 253a56bb8a5SSatoshi Asami 254a56bb8a5SSatoshi Asami /* XXX: is this necessary? */ 255a56bb8a5SSatoshi Asami for (i = 0; i < numccd; ++i) 256a56bb8a5SSatoshi Asami ccddevs[i].ccd_dk = -1; 257d8594dfbSSatoshi Asami 258d8594dfbSSatoshi Asami dev_attach(&kdc_ccd[dp->id_unit]); 259d8594dfbSSatoshi Asami return 1; 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]; 269a56bb8a5SSatoshi Asami register struct ccdcinfo *ci; 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 */ 375a56bb8a5SSatoshi Asami if (size < 0) 376a56bb8a5SSatoshi Asami size = 0; 377a56bb8a5SSatoshi Asami 378a56bb8a5SSatoshi Asami if (cs->sc_ileave > 1) 379a56bb8a5SSatoshi Asami size -= size % cs->sc_ileave; 380a56bb8a5SSatoshi Asami 381a56bb8a5SSatoshi Asami if (size == 0) { 382a56bb8a5SSatoshi Asami #ifdef DEBUG 383a56bb8a5SSatoshi Asami if (ccddebug & (CCDB_FOLLOW|CCDB_INIT)) 384a56bb8a5SSatoshi Asami printf("ccd%d: %s: size == 0\n", 385a56bb8a5SSatoshi Asami ccd->ccd_unit, ci->ci_path); 386a56bb8a5SSatoshi Asami #endif 387a56bb8a5SSatoshi Asami free(ci->ci_path, M_DEVBUF); 388a56bb8a5SSatoshi Asami free(cs->sc_cinfo, M_DEVBUF); 389a56bb8a5SSatoshi Asami return (ENODEV); 390a56bb8a5SSatoshi Asami } 391a56bb8a5SSatoshi Asami 392a56bb8a5SSatoshi Asami if (minsize == 0 || size < minsize) 393a56bb8a5SSatoshi Asami minsize = size; 394a56bb8a5SSatoshi Asami ci->ci_size = size; 395a56bb8a5SSatoshi Asami cs->sc_size += size; 396a56bb8a5SSatoshi Asami } 397a56bb8a5SSatoshi Asami 398a56bb8a5SSatoshi Asami /* 399a56bb8a5SSatoshi Asami * Don't allow the interleave to be smaller than 400a56bb8a5SSatoshi Asami * the biggest component sector. 401a56bb8a5SSatoshi Asami */ 402a56bb8a5SSatoshi Asami if ((cs->sc_ileave > 0) && 403a56bb8a5SSatoshi Asami (cs->sc_ileave < (maxsecsize / DEV_BSIZE))) { 404a56bb8a5SSatoshi Asami #ifdef DEBUG 405a56bb8a5SSatoshi Asami if (ccddebug & (CCDB_FOLLOW|CCDB_INIT)) 406a56bb8a5SSatoshi Asami printf("ccd%d: interleave must be at least %d\n", 407a56bb8a5SSatoshi Asami ccd->ccd_unit, (maxsecsize / DEV_BSIZE)); 408a56bb8a5SSatoshi Asami #endif 409a56bb8a5SSatoshi Asami free(ci->ci_path, M_DEVBUF); 410a56bb8a5SSatoshi Asami free(cs->sc_cinfo, M_DEVBUF); 411a56bb8a5SSatoshi Asami return (EINVAL); 412a56bb8a5SSatoshi Asami } 413a56bb8a5SSatoshi Asami 414a56bb8a5SSatoshi Asami /* 415a56bb8a5SSatoshi Asami * If uniform interleave is desired set all sizes to that of 416a56bb8a5SSatoshi Asami * the smallest component. 417a56bb8a5SSatoshi Asami */ 418a56bb8a5SSatoshi Asami if (ccd->ccd_flags & CCDF_UNIFORM) { 419a56bb8a5SSatoshi Asami for (ci = cs->sc_cinfo; 420a56bb8a5SSatoshi Asami ci < &cs->sc_cinfo[cs->sc_nccdisks]; ci++) 421a56bb8a5SSatoshi Asami ci->ci_size = minsize; 42209b59204SSatoshi Asami if (ccd->ccd_flags & CCDF_MIRROR) { 42309b59204SSatoshi Asami if (cs->sc_nccdisks % 2) { 42409b59204SSatoshi Asami cs->sc_nccdisks--; 42509b59204SSatoshi Asami printf("ccd%d: mirroring requires even number of disks; using %d\n", 42609b59204SSatoshi Asami ccd->ccd_unit, cs->sc_nccdisks); 42709b59204SSatoshi Asami } 42809b59204SSatoshi Asami cs->sc_size = (cs->sc_nccdisks/2) * minsize; 42909b59204SSatoshi Asami } 43009b59204SSatoshi Asami else if (ccd->ccd_flags & CCDF_PARITY) 4317ecb65faSSatoshi Asami cs->sc_size = (cs->sc_nccdisks-1) * minsize; 4327ecb65faSSatoshi Asami else 433a56bb8a5SSatoshi Asami cs->sc_size = cs->sc_nccdisks * minsize; 434a56bb8a5SSatoshi Asami } 435a56bb8a5SSatoshi Asami 436a56bb8a5SSatoshi Asami /* 437a56bb8a5SSatoshi Asami * Construct the interleave table. 438a56bb8a5SSatoshi Asami */ 439a56bb8a5SSatoshi Asami ccdinterleave(cs, ccd->ccd_unit); 440a56bb8a5SSatoshi Asami 441a56bb8a5SSatoshi Asami /* 442a56bb8a5SSatoshi Asami * Create pseudo-geometry based on 1MB cylinders. It's 443a56bb8a5SSatoshi Asami * pretty close. 444a56bb8a5SSatoshi Asami */ 445a56bb8a5SSatoshi Asami ccg->ccg_secsize = DEV_BSIZE; 446a56bb8a5SSatoshi Asami ccg->ccg_ntracks = 1; 447a56bb8a5SSatoshi Asami ccg->ccg_nsectors = 1024 * (1024 / ccg->ccg_secsize); 448a56bb8a5SSatoshi Asami ccg->ccg_ncylinders = cs->sc_size / ccg->ccg_nsectors; 449a56bb8a5SSatoshi Asami 450a56bb8a5SSatoshi Asami #ifdef WORKING_DISK_STATISTICS /* XXX !! */ 451a56bb8a5SSatoshi Asami if (ccd->ccd_dk >= 0) 452a56bb8a5SSatoshi Asami dk_wpms[ccd->ccd_dk] = 32 * (60 * DEV_BSIZE / 2); /* XXX */ 453a56bb8a5SSatoshi Asami #endif 454a56bb8a5SSatoshi Asami 455a56bb8a5SSatoshi Asami cs->sc_flags |= CCDF_INITED; 456a56bb8a5SSatoshi Asami cs->sc_cflags = ccd->ccd_flags; /* So we can find out later... */ 457a56bb8a5SSatoshi Asami cs->sc_unit = ccd->ccd_unit; 458a56bb8a5SSatoshi Asami return (0); 459a56bb8a5SSatoshi Asami } 460a56bb8a5SSatoshi Asami 461a56bb8a5SSatoshi Asami static void 462a56bb8a5SSatoshi Asami ccdinterleave(cs, unit) 463a56bb8a5SSatoshi Asami register struct ccd_softc *cs; 464a56bb8a5SSatoshi Asami int unit; 465a56bb8a5SSatoshi Asami { 466a56bb8a5SSatoshi Asami register struct ccdcinfo *ci, *smallci; 467a56bb8a5SSatoshi Asami register struct ccdiinfo *ii; 468a56bb8a5SSatoshi Asami register daddr_t bn, lbn; 469a56bb8a5SSatoshi Asami register int ix; 470a56bb8a5SSatoshi Asami u_long size; 471a56bb8a5SSatoshi Asami 472a56bb8a5SSatoshi Asami #ifdef DEBUG 473a56bb8a5SSatoshi Asami if (ccddebug & CCDB_INIT) 474a56bb8a5SSatoshi Asami printf("ccdinterleave(%x): ileave %d\n", cs, cs->sc_ileave); 475a56bb8a5SSatoshi Asami #endif 476a56bb8a5SSatoshi Asami /* 477a56bb8a5SSatoshi Asami * Allocate an interleave table. 478a56bb8a5SSatoshi Asami * Chances are this is too big, but we don't care. 479a56bb8a5SSatoshi Asami */ 480a56bb8a5SSatoshi Asami size = (cs->sc_nccdisks + 1) * sizeof(struct ccdiinfo); 481a56bb8a5SSatoshi Asami cs->sc_itable = (struct ccdiinfo *)malloc(size, M_DEVBUF, M_WAITOK); 482a56bb8a5SSatoshi Asami bzero((caddr_t)cs->sc_itable, size); 483a56bb8a5SSatoshi Asami 484a56bb8a5SSatoshi Asami /* 485a56bb8a5SSatoshi Asami * Trivial case: no interleave (actually interleave of disk size). 486a56bb8a5SSatoshi Asami * Each table entry represents a single component in its entirety. 487a56bb8a5SSatoshi Asami */ 488a56bb8a5SSatoshi Asami if (cs->sc_ileave == 0) { 489a56bb8a5SSatoshi Asami bn = 0; 490a56bb8a5SSatoshi Asami ii = cs->sc_itable; 491a56bb8a5SSatoshi Asami 492a56bb8a5SSatoshi Asami for (ix = 0; ix < cs->sc_nccdisks; ix++) { 493a56bb8a5SSatoshi Asami /* Allocate space for ii_index. */ 494a56bb8a5SSatoshi Asami ii->ii_index = malloc(sizeof(int), M_DEVBUF, M_WAITOK); 495a56bb8a5SSatoshi Asami ii->ii_ndisk = 1; 496a56bb8a5SSatoshi Asami ii->ii_startblk = bn; 497a56bb8a5SSatoshi Asami ii->ii_startoff = 0; 498a56bb8a5SSatoshi Asami ii->ii_index[0] = ix; 499a56bb8a5SSatoshi Asami bn += cs->sc_cinfo[ix].ci_size; 500a56bb8a5SSatoshi Asami ii++; 501a56bb8a5SSatoshi Asami } 502a56bb8a5SSatoshi Asami ii->ii_ndisk = 0; 503a56bb8a5SSatoshi Asami #ifdef DEBUG 504a56bb8a5SSatoshi Asami if (ccddebug & CCDB_INIT) 505a56bb8a5SSatoshi Asami printiinfo(cs->sc_itable); 506a56bb8a5SSatoshi Asami #endif 507a56bb8a5SSatoshi Asami return; 508a56bb8a5SSatoshi Asami } 509a56bb8a5SSatoshi Asami 510a56bb8a5SSatoshi Asami /* 511a56bb8a5SSatoshi Asami * The following isn't fast or pretty; it doesn't have to be. 512a56bb8a5SSatoshi Asami */ 513a56bb8a5SSatoshi Asami size = 0; 514a56bb8a5SSatoshi Asami bn = lbn = 0; 515a56bb8a5SSatoshi Asami for (ii = cs->sc_itable; ; ii++) { 516a56bb8a5SSatoshi Asami /* Allocate space for ii_index. */ 517a56bb8a5SSatoshi Asami ii->ii_index = malloc((sizeof(int) * cs->sc_nccdisks), 518a56bb8a5SSatoshi Asami M_DEVBUF, M_WAITOK); 519a56bb8a5SSatoshi Asami 520a56bb8a5SSatoshi Asami /* 521a56bb8a5SSatoshi Asami * Locate the smallest of the remaining components 522a56bb8a5SSatoshi Asami */ 523a56bb8a5SSatoshi Asami smallci = NULL; 524a56bb8a5SSatoshi Asami for (ci = cs->sc_cinfo; 525a56bb8a5SSatoshi Asami ci < &cs->sc_cinfo[cs->sc_nccdisks]; ci++) 526a56bb8a5SSatoshi Asami if (ci->ci_size > size && 527a56bb8a5SSatoshi Asami (smallci == NULL || 528a56bb8a5SSatoshi Asami ci->ci_size < smallci->ci_size)) 529a56bb8a5SSatoshi Asami smallci = ci; 530a56bb8a5SSatoshi Asami 531a56bb8a5SSatoshi Asami /* 532a56bb8a5SSatoshi Asami * Nobody left, all done 533a56bb8a5SSatoshi Asami */ 534a56bb8a5SSatoshi Asami if (smallci == NULL) { 535a56bb8a5SSatoshi Asami ii->ii_ndisk = 0; 536a56bb8a5SSatoshi Asami break; 537a56bb8a5SSatoshi Asami } 538a56bb8a5SSatoshi Asami 539a56bb8a5SSatoshi Asami /* 540a56bb8a5SSatoshi Asami * Record starting logical block and component offset 541a56bb8a5SSatoshi Asami */ 542a56bb8a5SSatoshi Asami ii->ii_startblk = bn / cs->sc_ileave; 543a56bb8a5SSatoshi Asami ii->ii_startoff = lbn; 544a56bb8a5SSatoshi Asami 545a56bb8a5SSatoshi Asami /* 546a56bb8a5SSatoshi Asami * Determine how many disks take part in this interleave 547a56bb8a5SSatoshi Asami * and record their indices. 548a56bb8a5SSatoshi Asami */ 549a56bb8a5SSatoshi Asami ix = 0; 550a56bb8a5SSatoshi Asami for (ci = cs->sc_cinfo; 551a56bb8a5SSatoshi Asami ci < &cs->sc_cinfo[cs->sc_nccdisks]; ci++) 552a56bb8a5SSatoshi Asami if (ci->ci_size >= smallci->ci_size) 553a56bb8a5SSatoshi Asami ii->ii_index[ix++] = ci - cs->sc_cinfo; 554a56bb8a5SSatoshi Asami ii->ii_ndisk = ix; 555a56bb8a5SSatoshi Asami bn += ix * (smallci->ci_size - size); 556a56bb8a5SSatoshi Asami lbn = smallci->ci_size / cs->sc_ileave; 557a56bb8a5SSatoshi Asami size = smallci->ci_size; 558a56bb8a5SSatoshi Asami } 559a56bb8a5SSatoshi Asami #ifdef DEBUG 560a56bb8a5SSatoshi Asami if (ccddebug & CCDB_INIT) 561a56bb8a5SSatoshi Asami printiinfo(cs->sc_itable); 562a56bb8a5SSatoshi Asami #endif 563a56bb8a5SSatoshi Asami } 564a56bb8a5SSatoshi Asami 565a56bb8a5SSatoshi Asami /* ARGSUSED */ 566a56bb8a5SSatoshi Asami int 567a56bb8a5SSatoshi Asami ccdopen(dev, flags, fmt, p) 568a56bb8a5SSatoshi Asami dev_t dev; 569a56bb8a5SSatoshi Asami int flags, fmt; 570a56bb8a5SSatoshi Asami struct proc *p; 571a56bb8a5SSatoshi Asami { 572a56bb8a5SSatoshi Asami int unit = ccdunit(dev); 573a56bb8a5SSatoshi Asami struct ccd_softc *cs; 574a56bb8a5SSatoshi Asami struct disklabel *lp; 575a56bb8a5SSatoshi Asami int error = 0, part, pmask; 576a56bb8a5SSatoshi Asami 577a56bb8a5SSatoshi Asami #ifdef DEBUG 578a56bb8a5SSatoshi Asami if (ccddebug & CCDB_FOLLOW) 579a56bb8a5SSatoshi Asami printf("ccdopen(%x, %x)\n", dev, flags); 580a56bb8a5SSatoshi Asami #endif 581a56bb8a5SSatoshi Asami if (unit >= numccd) 582a56bb8a5SSatoshi Asami return (ENXIO); 583a56bb8a5SSatoshi Asami cs = &ccd_softc[unit]; 584a56bb8a5SSatoshi Asami 585a56bb8a5SSatoshi Asami if (error = ccdlock(cs)) 586a56bb8a5SSatoshi Asami return (error); 587a56bb8a5SSatoshi Asami 588a56bb8a5SSatoshi Asami lp = &cs->sc_dkdev.dk_label; 589a56bb8a5SSatoshi Asami 590d8594dfbSSatoshi Asami part = ccdpart(dev); 591a56bb8a5SSatoshi Asami pmask = (1 << part); 592a56bb8a5SSatoshi Asami 593a56bb8a5SSatoshi Asami /* 594a56bb8a5SSatoshi Asami * If we're initialized, check to see if there are any other 595a56bb8a5SSatoshi Asami * open partitions. If not, then it's safe to update 596a56bb8a5SSatoshi Asami * the in-core disklabel. 597a56bb8a5SSatoshi Asami */ 598a56bb8a5SSatoshi Asami if ((cs->sc_flags & CCDF_INITED) && (cs->sc_dkdev.dk_openmask == 0)) 599a56bb8a5SSatoshi Asami ccdgetdisklabel(dev); 600a56bb8a5SSatoshi Asami 601a56bb8a5SSatoshi Asami /* Check that the partition exists. */ 602a56bb8a5SSatoshi Asami if (part != RAW_PART && ((part > lp->d_npartitions) || 603a56bb8a5SSatoshi Asami (lp->d_partitions[part].p_fstype == FS_UNUSED))) { 604a56bb8a5SSatoshi Asami error = ENXIO; 605a56bb8a5SSatoshi Asami goto done; 606a56bb8a5SSatoshi Asami } 607a56bb8a5SSatoshi Asami 608a56bb8a5SSatoshi Asami /* Prevent our unit from being unconfigured while open. */ 609a56bb8a5SSatoshi Asami switch (fmt) { 610a56bb8a5SSatoshi Asami case S_IFCHR: 611a56bb8a5SSatoshi Asami cs->sc_dkdev.dk_copenmask |= pmask; 612a56bb8a5SSatoshi Asami break; 613a56bb8a5SSatoshi Asami 614a56bb8a5SSatoshi Asami case S_IFBLK: 615a56bb8a5SSatoshi Asami cs->sc_dkdev.dk_bopenmask |= pmask; 616a56bb8a5SSatoshi Asami break; 617a56bb8a5SSatoshi Asami } 618a56bb8a5SSatoshi Asami cs->sc_dkdev.dk_openmask = 619a56bb8a5SSatoshi Asami cs->sc_dkdev.dk_copenmask | cs->sc_dkdev.dk_bopenmask; 620a56bb8a5SSatoshi Asami 621a56bb8a5SSatoshi Asami done: 622a56bb8a5SSatoshi Asami ccdunlock(cs); 623a56bb8a5SSatoshi Asami return (0); 624a56bb8a5SSatoshi Asami } 625a56bb8a5SSatoshi Asami 626a56bb8a5SSatoshi Asami /* ARGSUSED */ 627a56bb8a5SSatoshi Asami int 628a56bb8a5SSatoshi Asami ccdclose(dev, flags, fmt, p) 629a56bb8a5SSatoshi Asami dev_t dev; 630a56bb8a5SSatoshi Asami int flags, fmt; 631a56bb8a5SSatoshi Asami struct proc *p; 632a56bb8a5SSatoshi Asami { 633a56bb8a5SSatoshi Asami int unit = ccdunit(dev); 634a56bb8a5SSatoshi Asami struct ccd_softc *cs; 635a56bb8a5SSatoshi Asami int error = 0, part; 636a56bb8a5SSatoshi Asami 637a56bb8a5SSatoshi Asami #ifdef DEBUG 638a56bb8a5SSatoshi Asami if (ccddebug & CCDB_FOLLOW) 639a56bb8a5SSatoshi Asami printf("ccdclose(%x, %x)\n", dev, flags); 640a56bb8a5SSatoshi Asami #endif 641a56bb8a5SSatoshi Asami 642a56bb8a5SSatoshi Asami if (unit >= numccd) 643a56bb8a5SSatoshi Asami return (ENXIO); 644a56bb8a5SSatoshi Asami cs = &ccd_softc[unit]; 645a56bb8a5SSatoshi Asami 646a56bb8a5SSatoshi Asami if (error = ccdlock(cs)) 647a56bb8a5SSatoshi Asami return (error); 648a56bb8a5SSatoshi Asami 649d8594dfbSSatoshi Asami part = ccdpart(dev); 650a56bb8a5SSatoshi Asami 651a56bb8a5SSatoshi Asami /* ...that much closer to allowing unconfiguration... */ 652a56bb8a5SSatoshi Asami switch (fmt) { 653a56bb8a5SSatoshi Asami case S_IFCHR: 654a56bb8a5SSatoshi Asami cs->sc_dkdev.dk_copenmask &= ~(1 << part); 655a56bb8a5SSatoshi Asami break; 656a56bb8a5SSatoshi Asami 657a56bb8a5SSatoshi Asami case S_IFBLK: 658a56bb8a5SSatoshi Asami cs->sc_dkdev.dk_bopenmask &= ~(1 << part); 659a56bb8a5SSatoshi Asami break; 660a56bb8a5SSatoshi Asami } 661a56bb8a5SSatoshi Asami cs->sc_dkdev.dk_openmask = 662a56bb8a5SSatoshi Asami cs->sc_dkdev.dk_copenmask | cs->sc_dkdev.dk_bopenmask; 663a56bb8a5SSatoshi Asami 664a56bb8a5SSatoshi Asami ccdunlock(cs); 665a56bb8a5SSatoshi Asami return (0); 666a56bb8a5SSatoshi Asami } 667a56bb8a5SSatoshi Asami 668a56bb8a5SSatoshi Asami void 669a56bb8a5SSatoshi Asami ccdstrategy(bp) 670a56bb8a5SSatoshi Asami register struct buf *bp; 671a56bb8a5SSatoshi Asami { 672a56bb8a5SSatoshi Asami register int unit = ccdunit(bp->b_dev); 673a56bb8a5SSatoshi Asami register struct ccd_softc *cs = &ccd_softc[unit]; 674a56bb8a5SSatoshi Asami register daddr_t bn; 675a56bb8a5SSatoshi Asami register int sz, s; 676a56bb8a5SSatoshi Asami int wlabel; 677a56bb8a5SSatoshi Asami struct disklabel *lp; 678a56bb8a5SSatoshi Asami 679a56bb8a5SSatoshi Asami #ifdef DEBUG 680a56bb8a5SSatoshi Asami if (ccddebug & CCDB_FOLLOW) 681a56bb8a5SSatoshi Asami printf("ccdstrategy(%x): unit %d\n", bp, unit); 682a56bb8a5SSatoshi Asami #endif 683a56bb8a5SSatoshi Asami if ((cs->sc_flags & CCDF_INITED) == 0) { 684a56bb8a5SSatoshi Asami bp->b_error = ENXIO; 685a56bb8a5SSatoshi Asami bp->b_flags |= B_ERROR; 686a56bb8a5SSatoshi Asami goto done; 687a56bb8a5SSatoshi Asami } 688a56bb8a5SSatoshi Asami 689a56bb8a5SSatoshi Asami /* If it's a nil transfer, wake up the top half now. */ 690a56bb8a5SSatoshi Asami if (bp->b_bcount == 0) 691a56bb8a5SSatoshi Asami goto done; 692a56bb8a5SSatoshi Asami 693a56bb8a5SSatoshi Asami lp = &cs->sc_dkdev.dk_label; 694a56bb8a5SSatoshi Asami 695a56bb8a5SSatoshi Asami /* 696a56bb8a5SSatoshi Asami * Do bounds checking and adjust transfer. If there's an 697a56bb8a5SSatoshi Asami * error, the bounds check will flag that for us. 698a56bb8a5SSatoshi Asami */ 699a56bb8a5SSatoshi Asami wlabel = cs->sc_flags & (CCDF_WLABEL|CCDF_LABELLING); 700d8594dfbSSatoshi Asami if (ccdpart(bp->b_dev) != RAW_PART) 701a56bb8a5SSatoshi Asami if (bounds_check_with_label(bp, lp, wlabel) <= 0) 702a56bb8a5SSatoshi Asami goto done; 703a56bb8a5SSatoshi Asami 7043bc746beSSatoshi Asami if (cs->sc_cflags & CCDF_MIRROR && (bp->b_flags & B_READ) == 0) 7053bc746beSSatoshi Asami bp->b_resid = bp->b_bcount*2; 7063bc746beSSatoshi Asami else 707a56bb8a5SSatoshi Asami bp->b_resid = bp->b_bcount; 708a56bb8a5SSatoshi Asami 709a56bb8a5SSatoshi Asami /* 710a56bb8a5SSatoshi Asami * "Start" the unit. 711a56bb8a5SSatoshi Asami */ 712a56bb8a5SSatoshi Asami s = splbio(); 713a56bb8a5SSatoshi Asami ccdstart(cs, bp); 714a56bb8a5SSatoshi Asami splx(s); 715a56bb8a5SSatoshi Asami return; 716a56bb8a5SSatoshi Asami done: 717a56bb8a5SSatoshi Asami biodone(bp); 718a56bb8a5SSatoshi Asami } 719a56bb8a5SSatoshi Asami 720a56bb8a5SSatoshi Asami static void 721a56bb8a5SSatoshi Asami ccdstart(cs, bp) 722a56bb8a5SSatoshi Asami register struct ccd_softc *cs; 723a56bb8a5SSatoshi Asami register struct buf *bp; 724a56bb8a5SSatoshi Asami { 725a56bb8a5SSatoshi Asami register long bcount, rcount; 7263bc746beSSatoshi Asami struct ccdbuf *cbp[4]; 7273bc746beSSatoshi Asami /* XXX! : 2 reads and 2 writes for RAID 4/5 */ 728a56bb8a5SSatoshi Asami caddr_t addr; 729a56bb8a5SSatoshi Asami daddr_t bn; 730a56bb8a5SSatoshi Asami struct partition *pp; 731a56bb8a5SSatoshi Asami 732a56bb8a5SSatoshi Asami #ifdef DEBUG 733a56bb8a5SSatoshi Asami if (ccddebug & CCDB_FOLLOW) 734a56bb8a5SSatoshi Asami printf("ccdstart(%x, %x)\n", cs, bp); 735a56bb8a5SSatoshi Asami #endif 736a56bb8a5SSatoshi Asami 737a56bb8a5SSatoshi Asami #ifdef WORKING_DISK_STATISTICS /* XXX !! */ 738a56bb8a5SSatoshi Asami /* 739a56bb8a5SSatoshi Asami * Instrumentation (not very meaningful) 740a56bb8a5SSatoshi Asami */ 741a56bb8a5SSatoshi Asami cs->sc_nactive++; 742a56bb8a5SSatoshi Asami if (cs->sc_dk >= 0) { 743a56bb8a5SSatoshi Asami dk_busy |= 1 << cs->sc_dk; 744a56bb8a5SSatoshi Asami dk_xfer[cs->sc_dk]++; 745a56bb8a5SSatoshi Asami dk_wds[cs->sc_dk] += bp->b_bcount >> 6; 746a56bb8a5SSatoshi Asami } 747a56bb8a5SSatoshi Asami #endif 748a56bb8a5SSatoshi Asami 749a56bb8a5SSatoshi Asami /* 750a56bb8a5SSatoshi Asami * Translate the partition-relative block number to an absolute. 751a56bb8a5SSatoshi Asami */ 752a56bb8a5SSatoshi Asami bn = bp->b_blkno; 753d8594dfbSSatoshi Asami if (ccdpart(bp->b_dev) != RAW_PART) { 754d8594dfbSSatoshi Asami pp = &cs->sc_dkdev.dk_label.d_partitions[ccdpart(bp->b_dev)]; 755a56bb8a5SSatoshi Asami bn += pp->p_offset; 756a56bb8a5SSatoshi Asami } 757a56bb8a5SSatoshi Asami 758a56bb8a5SSatoshi Asami /* 759a56bb8a5SSatoshi Asami * Allocate component buffers and fire off the requests 760a56bb8a5SSatoshi Asami */ 761a56bb8a5SSatoshi Asami addr = bp->b_data; 762a56bb8a5SSatoshi Asami for (bcount = bp->b_bcount; bcount > 0; bcount -= rcount) { 7633bc746beSSatoshi Asami ccdbuffer(cbp, cs, bp, bn, addr, bcount); 7643bc746beSSatoshi Asami rcount = cbp[0]->cb_buf.b_bcount; 7653bc746beSSatoshi Asami if ((cbp[0]->cb_buf.b_flags & B_READ) == 0) 7663bc746beSSatoshi Asami cbp[0]->cb_buf.b_vp->v_numoutput++; 7673bc746beSSatoshi Asami VOP_STRATEGY(&cbp[0]->cb_buf); 7683bc746beSSatoshi Asami if (cs->sc_cflags & CCDF_MIRROR && 7693bc746beSSatoshi Asami (cbp[0]->cb_buf.b_flags & B_READ) == 0) { 7703bc746beSSatoshi Asami /* mirror, start another write */ 7713bc746beSSatoshi Asami cbp[1]->cb_buf.b_vp->v_numoutput++; 7723bc746beSSatoshi Asami VOP_STRATEGY(&cbp[1]->cb_buf); 7733bc746beSSatoshi Asami } 774a56bb8a5SSatoshi Asami bn += btodb(rcount); 775a56bb8a5SSatoshi Asami addr += rcount; 776a56bb8a5SSatoshi Asami } 777a56bb8a5SSatoshi Asami } 778a56bb8a5SSatoshi Asami 779a56bb8a5SSatoshi Asami /* 780a56bb8a5SSatoshi Asami * Build a component buffer header. 781a56bb8a5SSatoshi Asami */ 7823bc746beSSatoshi Asami void 7833bc746beSSatoshi Asami ccdbuffer(cb, cs, bp, bn, addr, bcount) 7843bc746beSSatoshi Asami register struct ccdbuf **cb; 785a56bb8a5SSatoshi Asami register struct ccd_softc *cs; 786a56bb8a5SSatoshi Asami struct buf *bp; 787a56bb8a5SSatoshi Asami daddr_t bn; 788a56bb8a5SSatoshi Asami caddr_t addr; 789a56bb8a5SSatoshi Asami long bcount; 790a56bb8a5SSatoshi Asami { 7913bc746beSSatoshi Asami register struct ccdcinfo *ci, *ci2; 792a56bb8a5SSatoshi Asami register struct ccdbuf *cbp; 793a56bb8a5SSatoshi Asami register daddr_t cbn, cboff; 794a56bb8a5SSatoshi Asami 795a56bb8a5SSatoshi Asami #ifdef DEBUG 796a56bb8a5SSatoshi Asami if (ccddebug & CCDB_IO) 797a56bb8a5SSatoshi Asami printf("ccdbuffer(%x, %x, %d, %x, %d)\n", 798a56bb8a5SSatoshi Asami cs, bp, bn, addr, bcount); 799a56bb8a5SSatoshi Asami #endif 800a56bb8a5SSatoshi Asami /* 801a56bb8a5SSatoshi Asami * Determine which component bn falls in. 802a56bb8a5SSatoshi Asami */ 803a56bb8a5SSatoshi Asami cbn = bn; 804a56bb8a5SSatoshi Asami cboff = 0; 805a56bb8a5SSatoshi Asami 806a56bb8a5SSatoshi Asami /* 807a56bb8a5SSatoshi Asami * Serially concatenated 808a56bb8a5SSatoshi Asami */ 809a56bb8a5SSatoshi Asami if (cs->sc_ileave == 0) { 810a56bb8a5SSatoshi Asami register daddr_t sblk; 811a56bb8a5SSatoshi Asami 812a56bb8a5SSatoshi Asami sblk = 0; 813a56bb8a5SSatoshi Asami for (ci = cs->sc_cinfo; cbn >= sblk + ci->ci_size; ci++) 814a56bb8a5SSatoshi Asami sblk += ci->ci_size; 815a56bb8a5SSatoshi Asami cbn -= sblk; 816a56bb8a5SSatoshi Asami } 817a56bb8a5SSatoshi Asami /* 818a56bb8a5SSatoshi Asami * Interleaved 819a56bb8a5SSatoshi Asami */ 820a56bb8a5SSatoshi Asami else { 821a56bb8a5SSatoshi Asami register struct ccdiinfo *ii; 822a56bb8a5SSatoshi Asami int ccdisk, off; 823a56bb8a5SSatoshi Asami 824a56bb8a5SSatoshi Asami cboff = cbn % cs->sc_ileave; 825a56bb8a5SSatoshi Asami cbn /= cs->sc_ileave; 826a56bb8a5SSatoshi Asami for (ii = cs->sc_itable; ii->ii_ndisk; ii++) 827a56bb8a5SSatoshi Asami if (ii->ii_startblk > cbn) 828a56bb8a5SSatoshi Asami break; 829a56bb8a5SSatoshi Asami ii--; 830a56bb8a5SSatoshi Asami off = cbn - ii->ii_startblk; 831a56bb8a5SSatoshi Asami if (ii->ii_ndisk == 1) { 832a56bb8a5SSatoshi Asami ccdisk = ii->ii_index[0]; 833a56bb8a5SSatoshi Asami cbn = ii->ii_startoff + off; 834a56bb8a5SSatoshi Asami } else { 83509b59204SSatoshi Asami if (cs->sc_cflags & CCDF_MIRROR) { 83609b59204SSatoshi Asami ccdisk = ii->ii_index[off % (ii->ii_ndisk/2)]; 83709b59204SSatoshi Asami cbn = ii->ii_startoff + off / (ii->ii_ndisk/2); 8383bc746beSSatoshi Asami /* mirrored data */ 8393bc746beSSatoshi Asami ci2 = &cs->sc_cinfo[ccdisk + ii->ii_ndisk/2]; 84009b59204SSatoshi Asami } 84109b59204SSatoshi Asami else if (cs->sc_cflags & CCDF_PARITY) { 8427ecb65faSSatoshi Asami ccdisk = ii->ii_index[off % (ii->ii_ndisk-1)]; 8437ecb65faSSatoshi Asami cbn = ii->ii_startoff + off / (ii->ii_ndisk-1); 8447ecb65faSSatoshi Asami if (cbn % ii->ii_ndisk <= ccdisk) 8457ecb65faSSatoshi Asami ccdisk++; 8467ecb65faSSatoshi Asami } 8477ecb65faSSatoshi Asami else { 848a56bb8a5SSatoshi Asami ccdisk = ii->ii_index[off % ii->ii_ndisk]; 849a56bb8a5SSatoshi Asami cbn = ii->ii_startoff + off / ii->ii_ndisk; 850a56bb8a5SSatoshi Asami } 8517ecb65faSSatoshi Asami } 852a56bb8a5SSatoshi Asami cbn *= cs->sc_ileave; 853a56bb8a5SSatoshi Asami ci = &cs->sc_cinfo[ccdisk]; 854a56bb8a5SSatoshi Asami } 855a56bb8a5SSatoshi Asami 856a56bb8a5SSatoshi Asami /* 857a56bb8a5SSatoshi Asami * Fill in the component buf structure. 858a56bb8a5SSatoshi Asami */ 859a56bb8a5SSatoshi Asami cbp = getccdbuf(); 860a56bb8a5SSatoshi Asami cbp->cb_buf.b_flags = bp->b_flags | B_CALL; 861a56bb8a5SSatoshi Asami cbp->cb_buf.b_iodone = (void (*)())ccdiodone; 862a56bb8a5SSatoshi Asami cbp->cb_buf.b_proc = bp->b_proc; 863a56bb8a5SSatoshi Asami cbp->cb_buf.b_dev = ci->ci_dev; /* XXX */ 864a56bb8a5SSatoshi Asami cbp->cb_buf.b_blkno = cbn + cboff; 865a56bb8a5SSatoshi Asami cbp->cb_buf.b_data = addr; 866a56bb8a5SSatoshi Asami cbp->cb_buf.b_vp = ci->ci_vp; 867a56bb8a5SSatoshi Asami if (cs->sc_ileave == 0) 868a56bb8a5SSatoshi Asami cbp->cb_buf.b_bcount = dbtob(ci->ci_size - cbn); 869a56bb8a5SSatoshi Asami else 870a56bb8a5SSatoshi Asami cbp->cb_buf.b_bcount = dbtob(cs->sc_ileave - cboff); 871a56bb8a5SSatoshi Asami if (cbp->cb_buf.b_bcount > bcount) 872a56bb8a5SSatoshi Asami cbp->cb_buf.b_bcount = bcount; 873a56bb8a5SSatoshi Asami 874a56bb8a5SSatoshi Asami /* 875a56bb8a5SSatoshi Asami * context for ccdiodone 876a56bb8a5SSatoshi Asami */ 877a56bb8a5SSatoshi Asami cbp->cb_obp = bp; 878a56bb8a5SSatoshi Asami cbp->cb_unit = cs - ccd_softc; 879a56bb8a5SSatoshi Asami cbp->cb_comp = ci - cs->sc_cinfo; 880a56bb8a5SSatoshi Asami 881a56bb8a5SSatoshi Asami #ifdef DEBUG 882a56bb8a5SSatoshi Asami if (ccddebug & CCDB_IO) 883a56bb8a5SSatoshi Asami printf(" dev %x(u%d): cbp %x bn %d addr %x bcnt %d\n", 884a56bb8a5SSatoshi Asami ci->ci_dev, ci-cs->sc_cinfo, cbp, cbp->cb_buf.b_blkno, 885a56bb8a5SSatoshi Asami cbp->cb_buf.b_data, cbp->cb_buf.b_bcount); 886a56bb8a5SSatoshi Asami #endif 8873bc746beSSatoshi Asami cb[0] = cbp; 8883bc746beSSatoshi Asami if (cs->sc_cflags & CCDF_MIRROR && 8893bc746beSSatoshi Asami (cbp->cb_buf.b_flags & B_READ) == 0) { 8903bc746beSSatoshi Asami /* mirror, start one more write */ 8913bc746beSSatoshi Asami cbp = getccdbuf(); 8923bc746beSSatoshi Asami *cbp = *cb[0]; 8933bc746beSSatoshi Asami cbp->cb_buf.b_dev = ci2->ci_dev; 8943bc746beSSatoshi Asami cbp->cb_buf.b_vp = ci2->ci_vp; 8953bc746beSSatoshi Asami cbp->cb_comp = ci2 - cs->sc_cinfo; 8963bc746beSSatoshi Asami cb[1] = cbp; 8973bc746beSSatoshi Asami } 898a56bb8a5SSatoshi Asami } 899a56bb8a5SSatoshi Asami 900a56bb8a5SSatoshi Asami static void 901a56bb8a5SSatoshi Asami ccdintr(cs, bp) 902a56bb8a5SSatoshi Asami register struct ccd_softc *cs; 903a56bb8a5SSatoshi Asami register struct buf *bp; 904a56bb8a5SSatoshi Asami { 905a56bb8a5SSatoshi Asami 906a56bb8a5SSatoshi Asami #ifdef DEBUG 907a56bb8a5SSatoshi Asami if (ccddebug & CCDB_FOLLOW) 908a56bb8a5SSatoshi Asami printf("ccdintr(%x, %x)\n", cs, bp); 909a56bb8a5SSatoshi Asami #endif 910a56bb8a5SSatoshi Asami /* 911a56bb8a5SSatoshi Asami * Request is done for better or worse, wakeup the top half. 912a56bb8a5SSatoshi Asami */ 913a56bb8a5SSatoshi Asami #ifdef WORKING_DISK_STATISTICS /* XXX !! */ 914a56bb8a5SSatoshi Asami --cs->sc_nactive; 915a56bb8a5SSatoshi Asami #ifdef DIAGNOSTIC 916a56bb8a5SSatoshi Asami if (cs->sc_nactive < 0) 917a56bb8a5SSatoshi Asami panic("ccdintr: ccd%d: sc_nactive < 0", cs->sc_unit); 918a56bb8a5SSatoshi Asami #endif 919a56bb8a5SSatoshi Asami 920a56bb8a5SSatoshi Asami if (cs->sc_nactive == 0 && cs->sc_dk >= 0) 921a56bb8a5SSatoshi Asami dk_busy &= ~(1 << cs->sc_dk); 922a56bb8a5SSatoshi Asami #endif 923a56bb8a5SSatoshi Asami if (bp->b_flags & B_ERROR) 9243bc746beSSatoshi Asami if (cs->sc_cflags & CCDF_MIRROR && (bp->b_flags & B_READ) == 0) 9253bc746beSSatoshi Asami bp->b_resid = bp->b_bcount*2; 9263bc746beSSatoshi Asami else 927a56bb8a5SSatoshi Asami bp->b_resid = bp->b_bcount; 928a56bb8a5SSatoshi Asami biodone(bp); 929a56bb8a5SSatoshi Asami } 930a56bb8a5SSatoshi Asami 931a56bb8a5SSatoshi Asami /* 932a56bb8a5SSatoshi Asami * Called at interrupt time. 933a56bb8a5SSatoshi Asami * Mark the component as done and if all components are done, 934a56bb8a5SSatoshi Asami * take a ccd interrupt. 935a56bb8a5SSatoshi Asami */ 936a56bb8a5SSatoshi Asami void 937a56bb8a5SSatoshi Asami ccdiodone(cbp) 938a56bb8a5SSatoshi Asami struct ccdbuf *cbp; 939a56bb8a5SSatoshi Asami { 940a56bb8a5SSatoshi Asami register struct buf *bp = cbp->cb_obp; 941a56bb8a5SSatoshi Asami register int unit = cbp->cb_unit; 942a56bb8a5SSatoshi Asami int count, s; 943a56bb8a5SSatoshi Asami 944a56bb8a5SSatoshi Asami s = splbio(); 945a56bb8a5SSatoshi Asami #ifdef DEBUG 946a56bb8a5SSatoshi Asami if (ccddebug & CCDB_FOLLOW) 947a56bb8a5SSatoshi Asami printf("ccdiodone(%x)\n", cbp); 948a56bb8a5SSatoshi Asami if (ccddebug & CCDB_IO) { 949a56bb8a5SSatoshi Asami printf("ccdiodone: bp %x bcount %d resid %d\n", 950a56bb8a5SSatoshi Asami bp, bp->b_bcount, bp->b_resid); 951a56bb8a5SSatoshi Asami printf(" dev %x(u%d), cbp %x bn %d addr %x bcnt %d\n", 952a56bb8a5SSatoshi Asami cbp->cb_buf.b_dev, cbp->cb_comp, cbp, 953a56bb8a5SSatoshi Asami cbp->cb_buf.b_blkno, cbp->cb_buf.b_data, 954a56bb8a5SSatoshi Asami cbp->cb_buf.b_bcount); 955a56bb8a5SSatoshi Asami } 956a56bb8a5SSatoshi Asami #endif 957a56bb8a5SSatoshi Asami 958a56bb8a5SSatoshi Asami if (cbp->cb_buf.b_flags & B_ERROR) { 959a56bb8a5SSatoshi Asami bp->b_flags |= B_ERROR; 960a56bb8a5SSatoshi Asami bp->b_error = cbp->cb_buf.b_error ? cbp->cb_buf.b_error : EIO; 961a56bb8a5SSatoshi Asami #ifdef DEBUG 962a56bb8a5SSatoshi Asami printf("ccd%d: error %d on component %d\n", 963a56bb8a5SSatoshi Asami unit, bp->b_error, cbp->cb_comp); 964a56bb8a5SSatoshi Asami #endif 965a56bb8a5SSatoshi Asami } 966a56bb8a5SSatoshi Asami count = cbp->cb_buf.b_bcount; 967a56bb8a5SSatoshi Asami putccdbuf(cbp); 968a56bb8a5SSatoshi Asami 969a56bb8a5SSatoshi Asami /* 970a56bb8a5SSatoshi Asami * If all done, "interrupt". 971a56bb8a5SSatoshi Asami */ 972a56bb8a5SSatoshi Asami bp->b_resid -= count; 973a56bb8a5SSatoshi Asami if (bp->b_resid < 0) 974a56bb8a5SSatoshi Asami panic("ccdiodone: count"); 975a56bb8a5SSatoshi Asami if (bp->b_resid == 0) 976a56bb8a5SSatoshi Asami ccdintr(&ccd_softc[unit], bp); 977a56bb8a5SSatoshi Asami splx(s); 978a56bb8a5SSatoshi Asami } 979a56bb8a5SSatoshi Asami 980a56bb8a5SSatoshi Asami /* ARGSUSED */ 981a56bb8a5SSatoshi Asami int 982a56bb8a5SSatoshi Asami ccdread(dev, uio, flags) 983a56bb8a5SSatoshi Asami dev_t dev; 984a56bb8a5SSatoshi Asami struct uio *uio; 985a56bb8a5SSatoshi Asami int flags; 986a56bb8a5SSatoshi Asami { 987a56bb8a5SSatoshi Asami int unit = ccdunit(dev); 988a56bb8a5SSatoshi Asami struct ccd_softc *cs; 989a56bb8a5SSatoshi Asami 990a56bb8a5SSatoshi Asami #ifdef DEBUG 991a56bb8a5SSatoshi Asami if (ccddebug & CCDB_FOLLOW) 992a56bb8a5SSatoshi Asami printf("ccdread(%x, %x)\n", dev, uio); 993a56bb8a5SSatoshi Asami #endif 994a56bb8a5SSatoshi Asami if (unit >= numccd) 995a56bb8a5SSatoshi Asami return (ENXIO); 996a56bb8a5SSatoshi Asami cs = &ccd_softc[unit]; 997a56bb8a5SSatoshi Asami 998a56bb8a5SSatoshi Asami if ((cs->sc_flags & CCDF_INITED) == 0) 999a56bb8a5SSatoshi Asami return (ENXIO); 1000a56bb8a5SSatoshi Asami 1001a56bb8a5SSatoshi Asami /* 1002a56bb8a5SSatoshi Asami * XXX: It's not clear that using minphys() is completely safe, 1003a56bb8a5SSatoshi Asami * in particular, for raw I/O. Underlying devices might have some 1004a56bb8a5SSatoshi Asami * non-obvious limits, because of the copy to user-space. 1005a56bb8a5SSatoshi Asami */ 1006a56bb8a5SSatoshi Asami return (physio(ccdstrategy, NULL, dev, B_READ, minphys, uio)); 1007a56bb8a5SSatoshi Asami } 1008a56bb8a5SSatoshi Asami 1009a56bb8a5SSatoshi Asami /* ARGSUSED */ 1010a56bb8a5SSatoshi Asami int 1011a56bb8a5SSatoshi Asami ccdwrite(dev, uio, flags) 1012a56bb8a5SSatoshi Asami dev_t dev; 1013a56bb8a5SSatoshi Asami struct uio *uio; 1014a56bb8a5SSatoshi Asami int flags; 1015a56bb8a5SSatoshi Asami { 1016a56bb8a5SSatoshi Asami int unit = ccdunit(dev); 1017a56bb8a5SSatoshi Asami struct ccd_softc *cs; 1018a56bb8a5SSatoshi Asami 1019a56bb8a5SSatoshi Asami #ifdef DEBUG 1020a56bb8a5SSatoshi Asami if (ccddebug & CCDB_FOLLOW) 1021a56bb8a5SSatoshi Asami printf("ccdwrite(%x, %x)\n", dev, uio); 1022a56bb8a5SSatoshi Asami #endif 1023a56bb8a5SSatoshi Asami if (unit >= numccd) 1024a56bb8a5SSatoshi Asami return (ENXIO); 1025a56bb8a5SSatoshi Asami cs = &ccd_softc[unit]; 1026a56bb8a5SSatoshi Asami 1027a56bb8a5SSatoshi Asami if ((cs->sc_flags & CCDF_INITED) == 0) 1028a56bb8a5SSatoshi Asami return (ENXIO); 1029a56bb8a5SSatoshi Asami 1030a56bb8a5SSatoshi Asami /* 1031a56bb8a5SSatoshi Asami * XXX: It's not clear that using minphys() is completely safe, 1032a56bb8a5SSatoshi Asami * in particular, for raw I/O. Underlying devices might have some 1033a56bb8a5SSatoshi Asami * non-obvious limits, because of the copy to user-space. 1034a56bb8a5SSatoshi Asami */ 1035a56bb8a5SSatoshi Asami return (physio(ccdstrategy, NULL, dev, B_WRITE, minphys, uio)); 1036a56bb8a5SSatoshi Asami } 1037a56bb8a5SSatoshi Asami 1038d8594dfbSSatoshi Asami static void 1039d8594dfbSSatoshi Asami loopdelay() 1040d8594dfbSSatoshi Asami { 1041d8594dfbSSatoshi Asami int i, j, k, l; 1042d8594dfbSSatoshi Asami printf("I'm now gonna wait for fifteen seconds\n"); 1043d8594dfbSSatoshi Asami printf("Press Ctl-Alt-Esc NOW!\n"); 1044d8594dfbSSatoshi Asami for (i = 0; i < 1000; i++) 1045d8594dfbSSatoshi Asami for (j = 0; j < 1000; j++) 1046d8594dfbSSatoshi Asami for (k = 0; k < 100; k++) 1047d8594dfbSSatoshi Asami l = i * j * k; 1048d8594dfbSSatoshi Asami } 1049d8594dfbSSatoshi Asami 1050a56bb8a5SSatoshi Asami int 1051a56bb8a5SSatoshi Asami ccdioctl(dev, cmd, data, flag, p) 1052a56bb8a5SSatoshi Asami dev_t dev; 1053d8594dfbSSatoshi Asami int cmd; 1054a56bb8a5SSatoshi Asami caddr_t data; 1055a56bb8a5SSatoshi Asami int flag; 1056a56bb8a5SSatoshi Asami struct proc *p; 1057a56bb8a5SSatoshi Asami { 1058a56bb8a5SSatoshi Asami int unit = ccdunit(dev); 1059a56bb8a5SSatoshi Asami int i, j, lookedup = 0, error = 0; 1060a56bb8a5SSatoshi Asami int part, pmask, s; 1061a56bb8a5SSatoshi Asami struct ccd_softc *cs; 1062a56bb8a5SSatoshi Asami struct ccd_ioctl *ccio = (struct ccd_ioctl *)data; 1063a56bb8a5SSatoshi Asami struct ccddevice ccd; 1064a56bb8a5SSatoshi Asami char **cpp; 1065a56bb8a5SSatoshi Asami struct vnode **vpp; 1066a56bb8a5SSatoshi Asami #ifdef WORKING_DISK_STATISTICS /* XXX !! */ 1067a56bb8a5SSatoshi Asami extern int dkn; 1068a56bb8a5SSatoshi Asami #endif 1069a56bb8a5SSatoshi Asami 1070a56bb8a5SSatoshi Asami if (unit >= numccd) 1071a56bb8a5SSatoshi Asami return (ENXIO); 1072a56bb8a5SSatoshi Asami cs = &ccd_softc[unit]; 1073a56bb8a5SSatoshi Asami 1074a56bb8a5SSatoshi Asami bzero(&ccd, sizeof(ccd)); 1075a56bb8a5SSatoshi Asami 1076a56bb8a5SSatoshi Asami switch (cmd) { 1077a56bb8a5SSatoshi Asami case CCDIOCSET: 1078a56bb8a5SSatoshi Asami if (cs->sc_flags & CCDF_INITED) 1079a56bb8a5SSatoshi Asami return (EBUSY); 1080a56bb8a5SSatoshi Asami 1081a56bb8a5SSatoshi Asami if ((flag & FWRITE) == 0) 1082a56bb8a5SSatoshi Asami return (EBADF); 1083a56bb8a5SSatoshi Asami 1084a56bb8a5SSatoshi Asami if (error = ccdlock(cs)) 1085a56bb8a5SSatoshi Asami return (error); 1086a56bb8a5SSatoshi Asami 1087a56bb8a5SSatoshi Asami /* Fill in some important bits. */ 1088a56bb8a5SSatoshi Asami ccd.ccd_unit = unit; 1089a56bb8a5SSatoshi Asami ccd.ccd_interleave = ccio->ccio_ileave; 109009b59204SSatoshi Asami if ((ccio->ccio_flags & CCDF_MIRROR) && 109109b59204SSatoshi Asami (ccio->ccio_flags & CCDF_PARITY)) { 109209b59204SSatoshi Asami printf("ccd%d: can't specify both mirror and parity, using mirror\n", unit); 109309b59204SSatoshi Asami ccio->ccio_flags &= ~CCDF_PARITY; 109409b59204SSatoshi Asami } 109509b59204SSatoshi Asami if ((ccio->ccio_flags & (CCDF_MIRROR | CCDF_PARITY)) && 10967ecb65faSSatoshi Asami !(ccio->ccio_flags & CCDF_UNIFORM)) { 109709b59204SSatoshi Asami printf("ccd%d: mirror/parity forces uniform flag\n", 109809b59204SSatoshi Asami unit); 10997ecb65faSSatoshi Asami ccio->ccio_flags |= CCDF_UNIFORM; 11007ecb65faSSatoshi Asami } 1101a56bb8a5SSatoshi Asami ccd.ccd_flags = ccio->ccio_flags & CCDF_USERMASK; 1102a56bb8a5SSatoshi Asami 1103a56bb8a5SSatoshi Asami /* 1104a56bb8a5SSatoshi Asami * Allocate space for and copy in the array of 1105a56bb8a5SSatoshi Asami * componet pathnames and device numbers. 1106a56bb8a5SSatoshi Asami */ 1107a56bb8a5SSatoshi Asami cpp = malloc(ccio->ccio_ndisks * sizeof(char *), 1108a56bb8a5SSatoshi Asami M_DEVBUF, M_WAITOK); 1109a56bb8a5SSatoshi Asami vpp = malloc(ccio->ccio_ndisks * sizeof(struct vnode *), 1110a56bb8a5SSatoshi Asami M_DEVBUF, M_WAITOK); 1111a56bb8a5SSatoshi Asami 1112a56bb8a5SSatoshi Asami error = copyin((caddr_t)ccio->ccio_disks, (caddr_t)cpp, 1113a56bb8a5SSatoshi Asami ccio->ccio_ndisks * sizeof(char **)); 1114a56bb8a5SSatoshi Asami if (error) { 1115a56bb8a5SSatoshi Asami free(vpp, M_DEVBUF); 1116a56bb8a5SSatoshi Asami free(cpp, M_DEVBUF); 1117a56bb8a5SSatoshi Asami ccdunlock(cs); 1118a56bb8a5SSatoshi Asami return (error); 1119a56bb8a5SSatoshi Asami } 1120a56bb8a5SSatoshi Asami 1121a56bb8a5SSatoshi Asami #ifdef DEBUG 1122a56bb8a5SSatoshi Asami if (ccddebug & CCDB_INIT) 1123a56bb8a5SSatoshi Asami for (i = 0; i < ccio->ccio_ndisks; ++i) 1124a56bb8a5SSatoshi Asami printf("ccdioctl: component %d: 0x%x\n", 1125a56bb8a5SSatoshi Asami i, cpp[i]); 1126a56bb8a5SSatoshi Asami #endif 1127a56bb8a5SSatoshi Asami 1128a56bb8a5SSatoshi Asami for (i = 0; i < ccio->ccio_ndisks; ++i) { 1129a56bb8a5SSatoshi Asami #ifdef DEBUG 1130a56bb8a5SSatoshi Asami if (ccddebug & CCDB_INIT) 1131a56bb8a5SSatoshi Asami printf("ccdioctl: lookedup = %d\n", lookedup); 1132a56bb8a5SSatoshi Asami #endif 1133a56bb8a5SSatoshi Asami if (error = ccdlookup(cpp[i], p, &vpp[i])) { 1134a56bb8a5SSatoshi Asami for (j = 0; j < lookedup; ++j) 1135a56bb8a5SSatoshi Asami (void)vn_close(vpp[j], FREAD|FWRITE, 1136a56bb8a5SSatoshi Asami p->p_ucred, p); 1137a56bb8a5SSatoshi Asami free(vpp, M_DEVBUF); 1138a56bb8a5SSatoshi Asami free(cpp, M_DEVBUF); 1139a56bb8a5SSatoshi Asami ccdunlock(cs); 1140a56bb8a5SSatoshi Asami return (error); 1141a56bb8a5SSatoshi Asami } 1142a56bb8a5SSatoshi Asami ++lookedup; 1143a56bb8a5SSatoshi Asami } 1144a56bb8a5SSatoshi Asami ccd.ccd_cpp = cpp; 1145a56bb8a5SSatoshi Asami ccd.ccd_vpp = vpp; 1146a56bb8a5SSatoshi Asami ccd.ccd_ndev = ccio->ccio_ndisks; 1147a56bb8a5SSatoshi Asami 1148a56bb8a5SSatoshi Asami #ifdef WORKING_DISK_STATISTICS /* XXX !! */ 1149a56bb8a5SSatoshi Asami /* 1150a56bb8a5SSatoshi Asami * Assign disk index first so that init routine 1151a56bb8a5SSatoshi Asami * can use it (saves having the driver drag around 1152a56bb8a5SSatoshi Asami * the ccddevice pointer just to set up the dk_* 1153a56bb8a5SSatoshi Asami * info in the open routine). 1154a56bb8a5SSatoshi Asami */ 1155a56bb8a5SSatoshi Asami if (dkn < DK_NDRIVE) 1156a56bb8a5SSatoshi Asami ccd.ccd_dk = dkn++; 1157a56bb8a5SSatoshi Asami else 1158a56bb8a5SSatoshi Asami ccd.ccd_dk = -1; 1159a56bb8a5SSatoshi Asami #endif 1160a56bb8a5SSatoshi Asami 1161a56bb8a5SSatoshi Asami /* 1162a56bb8a5SSatoshi Asami * Initialize the ccd. Fills in the softc for us. 1163a56bb8a5SSatoshi Asami */ 1164a56bb8a5SSatoshi Asami if (error = ccdinit(&ccd, cpp, p)) { 1165a56bb8a5SSatoshi Asami #ifdef WORKING_DISK_STATISTICS /* XXX !! */ 1166a56bb8a5SSatoshi Asami if (ccd.ccd_dk >= 0) 1167a56bb8a5SSatoshi Asami --dkn; 1168a56bb8a5SSatoshi Asami #endif 1169a56bb8a5SSatoshi Asami for (j = 0; j < lookedup; ++j) 1170a56bb8a5SSatoshi Asami (void)vn_close(vpp[j], FREAD|FWRITE, 1171a56bb8a5SSatoshi Asami p->p_ucred, p); 1172a56bb8a5SSatoshi Asami bzero(&ccd_softc[unit], sizeof(struct ccd_softc)); 1173a56bb8a5SSatoshi Asami free(vpp, M_DEVBUF); 1174a56bb8a5SSatoshi Asami free(cpp, M_DEVBUF); 1175a56bb8a5SSatoshi Asami ccdunlock(cs); 1176a56bb8a5SSatoshi Asami return (error); 1177a56bb8a5SSatoshi Asami } 1178a56bb8a5SSatoshi Asami 1179a56bb8a5SSatoshi Asami /* 1180a56bb8a5SSatoshi Asami * The ccd has been successfully initialized, so 1181a56bb8a5SSatoshi Asami * we can place it into the array and read the disklabel. 1182a56bb8a5SSatoshi Asami */ 1183a56bb8a5SSatoshi Asami bcopy(&ccd, &ccddevs[unit], sizeof(ccd)); 1184a56bb8a5SSatoshi Asami ccio->ccio_unit = unit; 1185a56bb8a5SSatoshi Asami ccio->ccio_size = cs->sc_size; 1186a56bb8a5SSatoshi Asami ccdgetdisklabel(dev); 1187a56bb8a5SSatoshi Asami 1188a56bb8a5SSatoshi Asami ccdunlock(cs); 1189a56bb8a5SSatoshi Asami 1190a56bb8a5SSatoshi Asami break; 1191a56bb8a5SSatoshi Asami 1192a56bb8a5SSatoshi Asami case CCDIOCCLR: 1193a56bb8a5SSatoshi Asami if ((cs->sc_flags & CCDF_INITED) == 0) 1194a56bb8a5SSatoshi Asami return (ENXIO); 1195a56bb8a5SSatoshi Asami 1196a56bb8a5SSatoshi Asami if ((flag & FWRITE) == 0) 1197a56bb8a5SSatoshi Asami return (EBADF); 1198a56bb8a5SSatoshi Asami 1199a56bb8a5SSatoshi Asami if (error = ccdlock(cs)) 1200a56bb8a5SSatoshi Asami return (error); 1201a56bb8a5SSatoshi Asami 1202a56bb8a5SSatoshi Asami /* 1203a56bb8a5SSatoshi Asami * Don't unconfigure if any other partitions are open 1204a56bb8a5SSatoshi Asami * or if both the character and block flavors of this 1205a56bb8a5SSatoshi Asami * partition are open. 1206a56bb8a5SSatoshi Asami */ 1207d8594dfbSSatoshi Asami part = ccdpart(dev); 1208a56bb8a5SSatoshi Asami pmask = (1 << part); 1209a56bb8a5SSatoshi Asami if ((cs->sc_dkdev.dk_openmask & ~pmask) || 1210a56bb8a5SSatoshi Asami ((cs->sc_dkdev.dk_bopenmask & pmask) && 1211a56bb8a5SSatoshi Asami (cs->sc_dkdev.dk_copenmask & pmask))) { 1212a56bb8a5SSatoshi Asami ccdunlock(cs); 1213a56bb8a5SSatoshi Asami return (EBUSY); 1214a56bb8a5SSatoshi Asami } 1215a56bb8a5SSatoshi Asami 1216a56bb8a5SSatoshi Asami /* 1217a56bb8a5SSatoshi Asami * Free ccd_softc information and clear entry. 1218a56bb8a5SSatoshi Asami */ 1219a56bb8a5SSatoshi Asami 1220a56bb8a5SSatoshi Asami /* Close the components and free their pathnames. */ 1221a56bb8a5SSatoshi Asami for (i = 0; i < cs->sc_nccdisks; ++i) { 1222a56bb8a5SSatoshi Asami /* 1223a56bb8a5SSatoshi Asami * XXX: this close could potentially fail and 1224a56bb8a5SSatoshi Asami * cause Bad Things. Maybe we need to force 1225a56bb8a5SSatoshi Asami * the close to happen? 1226a56bb8a5SSatoshi Asami */ 1227a56bb8a5SSatoshi Asami #ifdef DEBUG 1228a56bb8a5SSatoshi Asami if (ccddebug & CCDB_VNODE) 1229a56bb8a5SSatoshi Asami vprint("CCDIOCCLR: vnode info", 1230a56bb8a5SSatoshi Asami cs->sc_cinfo[i].ci_vp); 1231a56bb8a5SSatoshi Asami #endif 1232a56bb8a5SSatoshi Asami (void)vn_close(cs->sc_cinfo[i].ci_vp, FREAD|FWRITE, 1233a56bb8a5SSatoshi Asami p->p_ucred, p); 1234a56bb8a5SSatoshi Asami free(cs->sc_cinfo[i].ci_path, M_DEVBUF); 1235a56bb8a5SSatoshi Asami } 1236a56bb8a5SSatoshi Asami 1237a56bb8a5SSatoshi Asami /* Free interleave index. */ 1238a56bb8a5SSatoshi Asami for (i = 0; cs->sc_itable[i].ii_ndisk; ++i) 1239a56bb8a5SSatoshi Asami free(cs->sc_itable[i].ii_index, M_DEVBUF); 1240a56bb8a5SSatoshi Asami 1241a56bb8a5SSatoshi Asami /* Free component info and interleave table. */ 1242a56bb8a5SSatoshi Asami free(cs->sc_cinfo, M_DEVBUF); 1243a56bb8a5SSatoshi Asami free(cs->sc_itable, M_DEVBUF); 1244a56bb8a5SSatoshi Asami cs->sc_flags &= ~CCDF_INITED; 1245a56bb8a5SSatoshi Asami 1246a56bb8a5SSatoshi Asami /* 1247a56bb8a5SSatoshi Asami * Free ccddevice information and clear entry. 1248a56bb8a5SSatoshi Asami */ 1249a56bb8a5SSatoshi Asami free(ccddevs[unit].ccd_cpp, M_DEVBUF); 1250a56bb8a5SSatoshi Asami free(ccddevs[unit].ccd_vpp, M_DEVBUF); 1251a56bb8a5SSatoshi Asami ccd.ccd_dk = -1; 1252a56bb8a5SSatoshi Asami bcopy(&ccd, &ccddevs[unit], sizeof(ccd)); 1253a56bb8a5SSatoshi Asami 1254a56bb8a5SSatoshi Asami /* This must be atomic. */ 1255a56bb8a5SSatoshi Asami s = splhigh(); 1256a56bb8a5SSatoshi Asami ccdunlock(cs); 1257a56bb8a5SSatoshi Asami bzero(cs, sizeof(struct ccd_softc)); 1258a56bb8a5SSatoshi Asami splx(s); 1259a56bb8a5SSatoshi Asami 1260a56bb8a5SSatoshi Asami break; 1261a56bb8a5SSatoshi Asami 1262a56bb8a5SSatoshi Asami case DIOCGDINFO: 1263a56bb8a5SSatoshi Asami if ((cs->sc_flags & CCDF_INITED) == 0) 1264a56bb8a5SSatoshi Asami return (ENXIO); 1265a56bb8a5SSatoshi Asami 1266a56bb8a5SSatoshi Asami *(struct disklabel *)data = cs->sc_dkdev.dk_label; 1267a56bb8a5SSatoshi Asami break; 1268a56bb8a5SSatoshi Asami 1269a56bb8a5SSatoshi Asami case DIOCGPART: 1270a56bb8a5SSatoshi Asami if ((cs->sc_flags & CCDF_INITED) == 0) 1271a56bb8a5SSatoshi Asami return (ENXIO); 1272a56bb8a5SSatoshi Asami 1273a56bb8a5SSatoshi Asami ((struct partinfo *)data)->disklab = &cs->sc_dkdev.dk_label; 1274a56bb8a5SSatoshi Asami ((struct partinfo *)data)->part = 1275d8594dfbSSatoshi Asami &cs->sc_dkdev.dk_label.d_partitions[ccdpart(dev)]; 1276a56bb8a5SSatoshi Asami break; 1277a56bb8a5SSatoshi Asami 1278a56bb8a5SSatoshi Asami case DIOCWDINFO: 1279a56bb8a5SSatoshi Asami case DIOCSDINFO: 1280a56bb8a5SSatoshi Asami if ((cs->sc_flags & CCDF_INITED) == 0) 1281a56bb8a5SSatoshi Asami return (ENXIO); 1282a56bb8a5SSatoshi Asami 1283a56bb8a5SSatoshi Asami if ((flag & FWRITE) == 0) 1284a56bb8a5SSatoshi Asami return (EBADF); 1285a56bb8a5SSatoshi Asami 1286a56bb8a5SSatoshi Asami if (error = ccdlock(cs)) 1287a56bb8a5SSatoshi Asami return (error); 1288a56bb8a5SSatoshi Asami 1289a56bb8a5SSatoshi Asami cs->sc_flags |= CCDF_LABELLING; 1290a56bb8a5SSatoshi Asami 1291a56bb8a5SSatoshi Asami error = setdisklabel(&cs->sc_dkdev.dk_label, 1292d8594dfbSSatoshi Asami (struct disklabel *)data, 0); 1293d8594dfbSSatoshi Asami /*, &cs->sc_dkdev.dk_cpulabel); */ 1294a56bb8a5SSatoshi Asami if (error == 0) { 1295a56bb8a5SSatoshi Asami if (cmd == DIOCWDINFO) 1296d8594dfbSSatoshi Asami error = correct_writedisklabel(CCDLABELDEV(dev), 1297d8594dfbSSatoshi Asami ccdstrategy, &cs->sc_dkdev.dk_label); 1298d8594dfbSSatoshi Asami /* 1299d8594dfbSSatoshi Asami &cs->sc_dkdev.dk_cpulabel); */ 1300a56bb8a5SSatoshi Asami } 1301a56bb8a5SSatoshi Asami 1302a56bb8a5SSatoshi Asami cs->sc_flags &= ~CCDF_LABELLING; 1303a56bb8a5SSatoshi Asami 1304a56bb8a5SSatoshi Asami ccdunlock(cs); 1305a56bb8a5SSatoshi Asami 1306a56bb8a5SSatoshi Asami if (error) 1307a56bb8a5SSatoshi Asami return (error); 1308a56bb8a5SSatoshi Asami break; 1309a56bb8a5SSatoshi Asami 1310a56bb8a5SSatoshi Asami case DIOCWLABEL: 1311a56bb8a5SSatoshi Asami if ((cs->sc_flags & CCDF_INITED) == 0) 1312a56bb8a5SSatoshi Asami return (ENXIO); 1313a56bb8a5SSatoshi Asami 1314a56bb8a5SSatoshi Asami if ((flag & FWRITE) == 0) 1315a56bb8a5SSatoshi Asami return (EBADF); 1316a56bb8a5SSatoshi Asami if (*(int *)data != 0) 1317a56bb8a5SSatoshi Asami cs->sc_flags |= CCDF_WLABEL; 1318a56bb8a5SSatoshi Asami else 1319a56bb8a5SSatoshi Asami cs->sc_flags &= ~CCDF_WLABEL; 1320a56bb8a5SSatoshi Asami break; 1321a56bb8a5SSatoshi Asami 1322a56bb8a5SSatoshi Asami default: 1323a56bb8a5SSatoshi Asami return (ENOTTY); 1324a56bb8a5SSatoshi Asami } 1325a56bb8a5SSatoshi Asami 1326a56bb8a5SSatoshi Asami return (0); 1327a56bb8a5SSatoshi Asami } 1328a56bb8a5SSatoshi Asami 1329a56bb8a5SSatoshi Asami int 1330a56bb8a5SSatoshi Asami ccdsize(dev) 1331a56bb8a5SSatoshi Asami dev_t dev; 1332a56bb8a5SSatoshi Asami { 1333a56bb8a5SSatoshi Asami struct ccd_softc *cs; 1334a56bb8a5SSatoshi Asami int part, size; 1335a56bb8a5SSatoshi Asami 1336a56bb8a5SSatoshi Asami if (ccdopen(dev, 0, S_IFBLK, curproc)) 1337a56bb8a5SSatoshi Asami return (-1); 1338a56bb8a5SSatoshi Asami 1339a56bb8a5SSatoshi Asami cs = &ccd_softc[ccdunit(dev)]; 1340d8594dfbSSatoshi Asami part = ccdpart(dev); 1341a56bb8a5SSatoshi Asami 1342a56bb8a5SSatoshi Asami if ((cs->sc_flags & CCDF_INITED) == 0) 1343a56bb8a5SSatoshi Asami return (-1); 1344a56bb8a5SSatoshi Asami 1345a56bb8a5SSatoshi Asami if (cs->sc_dkdev.dk_label.d_partitions[part].p_fstype != FS_SWAP) 1346a56bb8a5SSatoshi Asami size = -1; 1347a56bb8a5SSatoshi Asami else 1348a56bb8a5SSatoshi Asami size = cs->sc_dkdev.dk_label.d_partitions[part].p_size; 1349a56bb8a5SSatoshi Asami 1350a56bb8a5SSatoshi Asami if (ccdclose(dev, 0, S_IFBLK, curproc)) 1351a56bb8a5SSatoshi Asami return (-1); 1352a56bb8a5SSatoshi Asami 1353a56bb8a5SSatoshi Asami return (size); 1354a56bb8a5SSatoshi Asami } 1355a56bb8a5SSatoshi Asami 1356a56bb8a5SSatoshi Asami int 1357a56bb8a5SSatoshi Asami ccddump(dev, blkno, va, size) 1358a56bb8a5SSatoshi Asami dev_t dev; 1359a56bb8a5SSatoshi Asami daddr_t blkno; 1360a56bb8a5SSatoshi Asami caddr_t va; 1361a56bb8a5SSatoshi Asami size_t size; 1362a56bb8a5SSatoshi Asami { 1363a56bb8a5SSatoshi Asami 1364a56bb8a5SSatoshi Asami /* Not implemented. */ 1365a56bb8a5SSatoshi Asami return ENXIO; 1366a56bb8a5SSatoshi Asami } 1367a56bb8a5SSatoshi Asami 1368a56bb8a5SSatoshi Asami /* 1369a56bb8a5SSatoshi Asami * Lookup the provided name in the filesystem. If the file exists, 1370a56bb8a5SSatoshi Asami * is a valid block device, and isn't being used by anyone else, 1371a56bb8a5SSatoshi Asami * set *vpp to the file's vnode. 1372a56bb8a5SSatoshi Asami */ 1373a56bb8a5SSatoshi Asami static int 1374a56bb8a5SSatoshi Asami ccdlookup(path, p, vpp) 1375a56bb8a5SSatoshi Asami char *path; 1376a56bb8a5SSatoshi Asami struct proc *p; 1377a56bb8a5SSatoshi Asami struct vnode **vpp; /* result */ 1378a56bb8a5SSatoshi Asami { 1379a56bb8a5SSatoshi Asami struct nameidata nd; 1380a56bb8a5SSatoshi Asami struct vnode *vp; 1381a56bb8a5SSatoshi Asami struct vattr va; 1382a56bb8a5SSatoshi Asami int error; 1383a56bb8a5SSatoshi Asami 1384a56bb8a5SSatoshi Asami NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, path, p); 1385a56bb8a5SSatoshi Asami if (error = vn_open(&nd, FREAD|FWRITE, 0)) { 1386a56bb8a5SSatoshi Asami #ifdef DEBUG 1387a56bb8a5SSatoshi Asami if (ccddebug & CCDB_FOLLOW|CCDB_INIT) 1388a56bb8a5SSatoshi Asami printf("ccdlookup: vn_open error = %d\n", error); 1389a56bb8a5SSatoshi Asami #endif 1390a56bb8a5SSatoshi Asami return (error); 1391a56bb8a5SSatoshi Asami } 1392a56bb8a5SSatoshi Asami vp = nd.ni_vp; 1393a56bb8a5SSatoshi Asami 1394a56bb8a5SSatoshi Asami if (vp->v_usecount > 1) { 1395a56bb8a5SSatoshi Asami VOP_UNLOCK(vp); 1396a56bb8a5SSatoshi Asami (void)vn_close(vp, FREAD|FWRITE, p->p_ucred, p); 1397a56bb8a5SSatoshi Asami return (EBUSY); 1398a56bb8a5SSatoshi Asami } 1399a56bb8a5SSatoshi Asami 1400a56bb8a5SSatoshi Asami if (error = VOP_GETATTR(vp, &va, p->p_ucred, p)) { 1401a56bb8a5SSatoshi Asami #ifdef DEBUG 1402a56bb8a5SSatoshi Asami if (ccddebug & CCDB_FOLLOW|CCDB_INIT) 1403a56bb8a5SSatoshi Asami printf("ccdlookup: getattr error = %d\n", error); 1404a56bb8a5SSatoshi Asami #endif 1405a56bb8a5SSatoshi Asami VOP_UNLOCK(vp); 1406a56bb8a5SSatoshi Asami (void)vn_close(vp, FREAD|FWRITE, p->p_ucred, p); 1407a56bb8a5SSatoshi Asami return (error); 1408a56bb8a5SSatoshi Asami } 1409a56bb8a5SSatoshi Asami 1410a56bb8a5SSatoshi Asami /* XXX: eventually we should handle VREG, too. */ 1411a56bb8a5SSatoshi Asami if (va.va_type != VBLK) { 1412a56bb8a5SSatoshi Asami VOP_UNLOCK(vp); 1413a56bb8a5SSatoshi Asami (void)vn_close(vp, FREAD|FWRITE, p->p_ucred, p); 1414a56bb8a5SSatoshi Asami return (ENOTBLK); 1415a56bb8a5SSatoshi Asami } 1416a56bb8a5SSatoshi Asami 1417a56bb8a5SSatoshi Asami #ifdef DEBUG 1418a56bb8a5SSatoshi Asami if (ccddebug & CCDB_VNODE) 1419a56bb8a5SSatoshi Asami vprint("ccdlookup: vnode info", vp); 1420a56bb8a5SSatoshi Asami #endif 1421a56bb8a5SSatoshi Asami 1422a56bb8a5SSatoshi Asami VOP_UNLOCK(vp); 1423a56bb8a5SSatoshi Asami *vpp = vp; 1424a56bb8a5SSatoshi Asami return (0); 1425a56bb8a5SSatoshi Asami } 1426a56bb8a5SSatoshi Asami 1427a56bb8a5SSatoshi Asami /* 1428a56bb8a5SSatoshi Asami * Read the disklabel from the ccd. If one is not present, fake one 1429a56bb8a5SSatoshi Asami * up. 1430a56bb8a5SSatoshi Asami */ 1431a56bb8a5SSatoshi Asami static void 1432a56bb8a5SSatoshi Asami ccdgetdisklabel(dev) 1433a56bb8a5SSatoshi Asami dev_t dev; 1434a56bb8a5SSatoshi Asami { 1435a56bb8a5SSatoshi Asami int unit = ccdunit(dev); 1436a56bb8a5SSatoshi Asami struct ccd_softc *cs = &ccd_softc[unit]; 1437a56bb8a5SSatoshi Asami char *errstring; 1438a56bb8a5SSatoshi Asami struct disklabel *lp = &cs->sc_dkdev.dk_label; 1439d8594dfbSSatoshi Asami /* struct cpu_disklabel *clp = &cs->sc_dkdev.dk_cpulabel; */ 1440a56bb8a5SSatoshi Asami struct ccdgeom *ccg = &cs->sc_geom; 1441a56bb8a5SSatoshi Asami 1442d8594dfbSSatoshi Asami struct dos_partition dos_partdummy; 1443d8594dfbSSatoshi Asami struct dkbad dkbaddummy; 1444d8594dfbSSatoshi Asami 1445a56bb8a5SSatoshi Asami bzero(lp, sizeof(*lp)); 1446d8594dfbSSatoshi Asami /* bzero(clp, sizeof(*clp)); */ 1447a56bb8a5SSatoshi Asami 1448a56bb8a5SSatoshi Asami lp->d_secperunit = cs->sc_size; 1449a56bb8a5SSatoshi Asami lp->d_secsize = ccg->ccg_secsize; 1450a56bb8a5SSatoshi Asami lp->d_nsectors = ccg->ccg_nsectors; 1451a56bb8a5SSatoshi Asami lp->d_ntracks = ccg->ccg_ntracks; 1452a56bb8a5SSatoshi Asami lp->d_ncylinders = ccg->ccg_ncylinders; 1453a56bb8a5SSatoshi Asami lp->d_secpercyl = lp->d_ntracks * lp->d_nsectors; 1454a56bb8a5SSatoshi Asami 1455a56bb8a5SSatoshi Asami strncpy(lp->d_typename, "ccd", sizeof(lp->d_typename)); 1456a56bb8a5SSatoshi Asami lp->d_type = DTYPE_CCD; 1457a56bb8a5SSatoshi Asami strncpy(lp->d_packname, "fictitious", sizeof(lp->d_packname)); 1458a56bb8a5SSatoshi Asami lp->d_rpm = 3600; 1459a56bb8a5SSatoshi Asami lp->d_interleave = 1; 1460a56bb8a5SSatoshi Asami lp->d_flags = 0; 1461a56bb8a5SSatoshi Asami 1462a56bb8a5SSatoshi Asami lp->d_partitions[RAW_PART].p_offset = 0; 1463a56bb8a5SSatoshi Asami lp->d_partitions[RAW_PART].p_size = cs->sc_size; 1464a56bb8a5SSatoshi Asami lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED; 1465a56bb8a5SSatoshi Asami lp->d_npartitions = RAW_PART + 1; 1466a56bb8a5SSatoshi Asami 1467d8594dfbSSatoshi Asami lp->d_bbsize = BBSIZE; /* XXX */ 1468d8594dfbSSatoshi Asami lp->d_sbsize = SBSIZE; /* XXX */ 1469d8594dfbSSatoshi Asami 1470a56bb8a5SSatoshi Asami lp->d_magic = DISKMAGIC; 1471a56bb8a5SSatoshi Asami lp->d_magic2 = DISKMAGIC; 1472a56bb8a5SSatoshi Asami lp->d_checksum = dkcksum(&cs->sc_dkdev.dk_label); 1473a56bb8a5SSatoshi Asami 1474a56bb8a5SSatoshi Asami /* 1475a56bb8a5SSatoshi Asami * Call the generic disklabel extraction routine. 1476a56bb8a5SSatoshi Asami */ 1477d8594dfbSSatoshi Asami if (errstring = correct_readdisklabel(CCDLABELDEV(dev), ccdstrategy, 1478d8594dfbSSatoshi Asami &cs->sc_dkdev.dk_label/*, &dos_partdummy, &dkbaddummy*/)) 1479d8594dfbSSatoshi Asami /*, &cs->sc_dkdev.dk_cpulabel)) */ 1480a56bb8a5SSatoshi Asami ccdmakedisklabel(cs); 1481a56bb8a5SSatoshi Asami 1482a56bb8a5SSatoshi Asami #ifdef DEBUG 1483a56bb8a5SSatoshi Asami /* It's actually extremely common to have unlabeled ccds. */ 1484a56bb8a5SSatoshi Asami if (ccddebug & CCDB_LABEL) 1485a56bb8a5SSatoshi Asami if (errstring != NULL) 1486a56bb8a5SSatoshi Asami printf("ccd%d: %s\n", unit, errstring); 1487a56bb8a5SSatoshi Asami #endif 1488a56bb8a5SSatoshi Asami } 1489a56bb8a5SSatoshi Asami 1490a56bb8a5SSatoshi Asami /* 1491a56bb8a5SSatoshi Asami * Take care of things one might want to take care of in the event 1492a56bb8a5SSatoshi Asami * that a disklabel isn't present. 1493a56bb8a5SSatoshi Asami */ 1494a56bb8a5SSatoshi Asami static void 1495a56bb8a5SSatoshi Asami ccdmakedisklabel(cs) 1496a56bb8a5SSatoshi Asami struct ccd_softc *cs; 1497a56bb8a5SSatoshi Asami { 1498a56bb8a5SSatoshi Asami struct disklabel *lp = &cs->sc_dkdev.dk_label; 1499a56bb8a5SSatoshi Asami 1500a56bb8a5SSatoshi Asami /* 1501a56bb8a5SSatoshi Asami * For historical reasons, if there's no disklabel present 1502a56bb8a5SSatoshi Asami * the raw partition must be marked FS_BSDFFS. 1503a56bb8a5SSatoshi Asami */ 1504a56bb8a5SSatoshi Asami lp->d_partitions[RAW_PART].p_fstype = FS_BSDFFS; 1505a56bb8a5SSatoshi Asami 1506a56bb8a5SSatoshi Asami strncpy(lp->d_packname, "default label", sizeof(lp->d_packname)); 1507a56bb8a5SSatoshi Asami } 1508a56bb8a5SSatoshi Asami 1509a56bb8a5SSatoshi Asami /* 1510a56bb8a5SSatoshi Asami * Wait interruptibly for an exclusive lock. 1511a56bb8a5SSatoshi Asami * 1512a56bb8a5SSatoshi Asami * XXX 1513a56bb8a5SSatoshi Asami * Several drivers do this; it should be abstracted and made MP-safe. 1514a56bb8a5SSatoshi Asami */ 1515a56bb8a5SSatoshi Asami static int 1516a56bb8a5SSatoshi Asami ccdlock(cs) 1517a56bb8a5SSatoshi Asami struct ccd_softc *cs; 1518a56bb8a5SSatoshi Asami { 1519a56bb8a5SSatoshi Asami int error; 1520a56bb8a5SSatoshi Asami 1521a56bb8a5SSatoshi Asami while ((cs->sc_flags & CCDF_LOCKED) != 0) { 1522a56bb8a5SSatoshi Asami cs->sc_flags |= CCDF_WANTED; 1523a56bb8a5SSatoshi Asami if ((error = tsleep(cs, PRIBIO | PCATCH, "ccdlck", 0)) != 0) 1524a56bb8a5SSatoshi Asami return (error); 1525a56bb8a5SSatoshi Asami } 1526a56bb8a5SSatoshi Asami cs->sc_flags |= CCDF_LOCKED; 1527a56bb8a5SSatoshi Asami return (0); 1528a56bb8a5SSatoshi Asami } 1529a56bb8a5SSatoshi Asami 1530a56bb8a5SSatoshi Asami /* 1531a56bb8a5SSatoshi Asami * Unlock and wake up any waiters. 1532a56bb8a5SSatoshi Asami */ 1533a56bb8a5SSatoshi Asami static void 1534a56bb8a5SSatoshi Asami ccdunlock(cs) 1535a56bb8a5SSatoshi Asami struct ccd_softc *cs; 1536a56bb8a5SSatoshi Asami { 1537a56bb8a5SSatoshi Asami 1538a56bb8a5SSatoshi Asami cs->sc_flags &= ~CCDF_LOCKED; 1539a56bb8a5SSatoshi Asami if ((cs->sc_flags & CCDF_WANTED) != 0) { 1540a56bb8a5SSatoshi Asami cs->sc_flags &= ~CCDF_WANTED; 1541a56bb8a5SSatoshi Asami wakeup(cs); 1542a56bb8a5SSatoshi Asami } 1543a56bb8a5SSatoshi Asami } 1544a56bb8a5SSatoshi Asami 1545a56bb8a5SSatoshi Asami #ifdef DEBUG 1546a56bb8a5SSatoshi Asami static void 1547a56bb8a5SSatoshi Asami printiinfo(ii) 1548a56bb8a5SSatoshi Asami struct ccdiinfo *ii; 1549a56bb8a5SSatoshi Asami { 1550a56bb8a5SSatoshi Asami register int ix, i; 1551a56bb8a5SSatoshi Asami 1552a56bb8a5SSatoshi Asami for (ix = 0; ii->ii_ndisk; ix++, ii++) { 1553a56bb8a5SSatoshi Asami printf(" itab[%d]: #dk %d sblk %d soff %d", 1554a56bb8a5SSatoshi Asami ix, ii->ii_ndisk, ii->ii_startblk, ii->ii_startoff); 1555a56bb8a5SSatoshi Asami for (i = 0; i < ii->ii_ndisk; i++) 1556a56bb8a5SSatoshi Asami printf(" %d", ii->ii_index[i]); 1557a56bb8a5SSatoshi Asami printf("\n"); 1558a56bb8a5SSatoshi Asami } 1559a56bb8a5SSatoshi Asami } 1560a56bb8a5SSatoshi Asami #endif 1561d8594dfbSSatoshi Asami 1562d8594dfbSSatoshi Asami #endif /* NCCD > 0 */ 1563d8594dfbSSatoshi Asami 1564d8594dfbSSatoshi Asami /* Local Variables: */ 1565d8594dfbSSatoshi Asami /* c-argdecl-indent: 8 */ 156609b59204SSatoshi Asami /* c-continued-statement-offset: 8 */ 1567d8594dfbSSatoshi Asami /* c-indent-level: 8 */ 1568d8594dfbSSatoshi Asami /* End: */ 1569